Gutenberg block don’t save rich text content

Short Answer: When saving an attribute, always respect the attribute type. So if your attribute is of the array type, then save the value as an array, e.g. props.setAttributes( { innerContent: [ content ] } ).

Longer Answer

  1. Your register_block_type() call is missing the editor_script parameter. See the block editor handbook for details, but basically, you would need something like:

    function hall_register_block() {
        wp_register_script(
            'hall-block-server-side-render',
            '/path/to/block.js',
            array( 'wp-i18n', 'wp-blocks', 'wp-block-editor' ),
            '1.0'
        );
    
        register_block_type( 'hall/block-server-side-render', array(
            'render_callback' => 'hall_render_inner_content',
            'attributes'      => array(
                'innerContent' => array(
                    'type'    => 'array',
                    // You should set a default value:
                    'default' => array(), // if the attribute is an array
    //              'default' => '',      // if the attribute is a string
                ),
            ),
            // Here, your code is missing the block's script:
            'editor_script'   => 'hall-block-server-side-render',
        ) );
    }
    add_action( 'init', 'hall_register_block' );
    
  2. You defined the innerContent attribute as an array, so you would need to save it (via the props.setAttributes()) as an array:

    function onChangeContent( content ) {
        // Save the value as an array.
        props.setAttributes( { innerContent: [ content ] } );
    }
    

    And omit the attribute’s source and selector properties so that the attributes would be saved to (and read from) the block’s comment delimiter.

    attributes: {
        innerContent: {
            type: 'array',
            // No need for these two:
    //      source: 'children',
    //      selector: 'p'
        }
    },
    

    But then, in your block render callback (hall_render_inner_content()), you would also need to parse the HTML in the attribute value (which is not a simple array such as [ 'HTML here', 'another HTML here', 'etc etc' ]), and note that, in that callback, the $content is (or would supposedly be) an array and not a string.

    So you should probably just change the attribute type to string, i.e. just change the above type: 'array', to type: 'string',. And that way, you wouldn’t need to save the attribute as an array.

  3. You should import RichText from wp.blockEditor and not wp.editor:

    const { RichText } = wp.blockEditor; // use this
    const { RichText } = wp.editor;      // not this