簡體   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