1

I tried to create a container component that might change its inner component over time.

class Container extends React.Component {
    constructor(props) {
        super(props)
        this.state = { content: new FooComponent() }
    }
    render() {
        return <div>
            { this.state.content }
        </div>
    }
}

I get errors like:

Objects are not valid as a React child (found: object with keys {props, context, refs, updater, state}). If you meant to render a collection of children, use an array instead.

I tried { [this.state.component] }, but get same error.

Are you able to put components from this.state into the JSX that is returned from render()? If not, how do you implement a container? I'm thinking of creating a container something like iOS's UINavigationController, where I can push and pop components in a stack, with only the top one rendered to the screen.

Rob N
  • 15,024
  • 17
  • 92
  • 165
  • 1
    new will return an object (`this`) not the react component, use this: `content: `, later will get converted into `content: React.createElement(FooComponent, .....)`, but storing react component in state is not a good idea, better to store the relevent info in state to render that component. Check [**MDN Doc**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new), for more details about **how new operator works**. – Mayank Shukla Apr 23 '19 at 12:02

4 Answers4

2

You can use JSX: this.state = { content: <FooComponent/> }

Which is React.createElement() behind the scenes.

class Container extends React.Component {
    constructor(props) {
        super(props)
        this.state = { content: <FooComponent/> }
    }
    render() {
        return <div>{this.state.content}</div>;
    }
}

Or refer to Creating React Elements.

For reference here are more readable forms:

class Container extends React.Component {
  state = {
    content: <FooComponent />
  };

  render() {
    return <>{this.state.content}</>;
  }
}
function Container() {
  const [content, setContent] = useState(<FooComponent />);

  return <>{content}</>;
}
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
1

Can a React component render another component stored in it's state?

Yes you can!

There is two ways of doing it

1

import FooComponent from '..'

...
this.state = {
    content: <FooComponent/>
}
...
render(){
    return (
        <div>{this.state.content}</div>
    )
}

or

2

import FooComponent from '..'

...
this.state = {
    content: FooComponent
}
...
render(){
    const {
        content: BarComponent
    } = this.state

    return (
        <div>
            <BarComponent />
        </div>
    )
}

I get errors like:

Objects are not valid as a React child (found: object with keys {props, context, refs, updater, state}). If you meant to render a collection of children, use an array instead.

  • This happens because when you do new FooComponent() it returns an object and you can't render an object.
  • When using JSX, will be transpiled to React.createElement(FooComponent) and this is renderable.
  • When using only FooComponent, you store a reference to it and only in the render method you create a JSX that will become React.createElement(BarComponent)

The second aproach is good when the component is comming from props and you depending on the situation, you want to give it some props.

Working Example

Vencovsky
  • 28,550
  • 17
  • 109
  • 176
0
class Container extends React.Component {
 constructor(props) {
    super(props)
    this.state = { content: this.FooComponent() }
  }

 FooComponent(){
  return(<FooComponent/>)
 }

render() {
    return <div>
        { this.state.content }
    </div>
 }
}
Kishan Jaiswal
  • 644
  • 3
  • 14
0

The main question probably already answered there.

Notice: Limited functionality - storing only components will be a simple stateless view/screen stack/buffer.

The problem can be much wider. This solution won't be equal to saving previous states, changes ... no props/params, no history, no context, state reversing ... but shared common state (redux store) can be an advantage - no old states, autoupdating the whole chain of stored views.

xadm
  • 8,219
  • 3
  • 14
  • 25