将组件传递给 useState() 挂钩

6 javascript reactjs react-hooks

我正在尝试创建一个系统,其中我的应用程序组件的状态存储另一个组件,它将呈现该组件。任何组件都应该能够更新此状态,强制 App 组件重新渲染。

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

export default function App() {

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

    return (
        <div id="app">
            <Page/>
        </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

我知道如何使任何组件都可以访问该状态,但是在以应用程序的状态呈现组件时遇到一些问题。当我尝试运行上面的代码时,出现以下错误:

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

奇怪的是,将状态设置为 JSON 对象似乎可以解决该问题:

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

    return (
        <div id="app">
            <Page.Page/>
        </div>
    );
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有一种方法可以在没有 JSON 的情况下做到这一点。它似乎可以很好地处理数字和字符串;组件有什么不同?

小智 12

这是因为 的参数useState可以是两种类型之一:直接值或返回值的函数。返回值的函数称为惰性初始状态

例如:

useState('my value');
useState(() => 'my value');
Run Code Online (Sandbox Code Playgroud)

在直接传递 React 组件的情况下,它尝试将初始状态设置为组件的返回值,而不是组件本身。这就是导致它抛出错误的原因。

本质上,它试图做到这一点:

useState(() => <p>Hello world!</p>);
Run Code Online (Sandbox Code Playgroud)

解决方案?很简单,只需从该函数内部返回您的组件即可:

useState(() => Page1);
Run Code Online (Sandbox Code Playgroud)

  • 这实际上是正确的答案。这样做完全没问题,只是不应该到处这样做。您可以在 useState 中存储组件甚至函数,只需用箭头函数将其包装即可。 (3认同)

小智 8

实际上,您不应该将任何反应组件放入状态变量中。关于这一点,您可以查看此网站或类似的问题以了解更多详细信息。

现在,要完成这项工作,您只需使用一个对象来映射您需要的组件:

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>
    );
}
Run Code Online (Sandbox Code Playgroud)

这样,您只需更改状态中的对象键字符串,它就会重新加载您的打印组件。

  • 向组件添加 props 怎么样?Page1 和 Page2 可能会传递不同的 props (2认同)