Skip to content
Advertisement

Passing a component to the useState() hook

I’m trying to make a system where my App component’s state stores another component, which it will render. Any component should be able to update this state, forcing the App component to re-render.

function Page1() {
    return <p>Hello world!</p>
}

export default function App() {

    let [Page, setPage] = useState(Page1);

    return (
        <div id="app">
            <Page/>
        </div>
    );
}

I know how to make the state accessible by any component, but I’m having some issues with rendering the component in App’s state. When I try running the code above, I get the following error:

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

Strangely enough, making the state a JSON object seems to fix the issue:

let [Page, setPage] = useState({Page: Page1});

    return (
        <div id="app">
            <Page.Page/>
        </div>
    );

But I was wondering if there was a way to do this without the JSON. It seems to work fine with numbers and strings; what’s different about components?

Advertisement

Answer

Actually, you shouldn’t put any react component inside state variable. About this point, you can check this site or this similar question to read more details.

Now, to make this work you can just use an object to map the components you need:

function Page1() {
    return <p>Hello world!</p>
}

function Page2() {
    return <p>Hello world!</p>
}

const components = {
 'page1': Page1,
 'page2': Page2,
}

export default function App() {

    let [page, setPage] = useState('page1');

    return (
        <div id="app">
            <components.page />
        </div>
    );
}

In this way, you just have to change the object key string in the state and it should reload you printed component.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement