繁体   English   中英

当子组件在react钩子中调用useState()时,如何实现条件渲染?

[英]How to implement conditional rendering while the children component calling useState() in react hooks?

最近,我试图用React Hooks替换项目中的类组件实现,并且在实现有条件的子组件渲染时遇到一些麻烦。

我有一个父组件,该组件包含页眉,页脚和条件渲染子组件,该组件将根据父组件的状态来渲染不同的子组件,并且其状态由另一个useEffect进行控制,如下所述。

但是,我的一个子组件包含一个简单的计数器,该计数器由useState()实现,就像官方React Hooks教程中的示例一样。 正如钩子规则所述,我们只能在顶层调用钩子,因此渲染此子级时我的应用程序崩溃了。

我猜解决方案之一是将孩子的useState()放到父组件或使用类似Redux的实现? 但这有点尴尬,因为计数器只是一个简单的逻辑,不必从组件中取出。

因此,我正在寻找解决该问题的另一种方法。 当然,请先让我知道我的概念是否错误。

我的父组件:

const StorePage = (props) => {
    const { children } = props;
    const [detectedTagIds, setDetectedTagIds] = useState([]);
    const [detectedProducts, setDetectedProducts] = useState([]);

    const fetchProductByTagIds = (tagIds) => productController.getProducts({ tagId: tagIds })
        .then(res => res.json())
        .then(json => setDetectedProducts(json.result))

    // monitor detected tags
    useEffect(() => {
        ws.addEventListener('message', (event) => {
            const json = JSON.parse(event.data)
            const { tagId } = json;

            if (!_.includes(detectedTagIds, tagId)) {
                setDetectedTagIds(_.concat(detectedTagIds, tagId));
            }
        });
    }, []);

    // fetch while detected tags are changed
    useDeepCompareEffect(() => {
        fetchProductByTagIds(detectedTagIds)
    }, [detectedTagIds]);

    return (
        <div className="StorePage">
            {Header({ detectedProducts })}
            <div className="StorePage-content">
                {
                    detectedTagIds.length === 0 ?
                    LandingPage() :
                    ( detectedProducts.length === 1 ? ProductInfoPage({ detectedProduct: detectedProducts[0] }) : null )
                }
            </div>
            {Footer({ detectedProducts })}
        </div>
    );
};

export default StorePage;

这是我收到的错误消息,我认为这是由detectedProducts的更改触发的:

   Previous render            Next render
   ------------------------------------------------------
1. useState                   useState
2. useState                   useState
3. useEffect                  useEffect
4. useRef                     useRef
5. useEffect                  useEffect
6. useState                   useState
7. useState                   useState
8. useState                   useState
9. useRef                     useState
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

即使这些子组件使用了钩子,也可以有条件地呈现子组件,这是完全可以的,但是您需要使用常规的react方法:通过编写jsx标签或手动调用React.createElement(这是jsx编译的)进入)。 直接将子组件作为函数调用将导致您看到的问题。

return (
  <div className="StorePage">
    <Header detectedProducts={detectedProducts} />
    <div className="StorePage-content">
      {detectedTagIds.length === 0 ? (
        <LandingPage/>
      ) : detectedProducts.length == 1 ? (
        <ProductInfoPage detectedProducts={detectedProducts[0]} />
      ) : (
        null
      )}
    </div>
    <Footer detectedProducts={detectedProducts}/>
  </div>
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM