更改路线时,停止重新渲染组件。尤其是路线外的组件

时间:2020-08-06 13:11:31

标签: reactjs react-router

我具有以下组件结构:

  • 应用
    • 标题
    • 首页
    • 类别
    • 产品
      • 产品列表
      • 产品详情
        • ProductDetailMore

主要路线:

<div>
      <Header />

      <Switch>
        <Route exact path="/" render={() => <Home />} />
        <Route path="/category" render={() => <Categories />} />
        <Route path="/products" render={() => <Products />} />
      </Switch>
</div>

产品路线:

const productsData = [...]; 

return (
<div>
  <div>
    <ProductList data={productsData} />
  </div>

  <Switch>
    <Route path={`${match.url}/:productId`} render={()=>
      <ProductDetail data={productsData} />} />

    <Route exact path={match.url} render={()=> (
      <div style={{ textAlign: "center" }}>Select a product.</div>
    )} />
  </Switch>
</div>
);

以及ProductDetail中的路线:

return (
<>
  <div>
    <h3> {product.name} </h3>
    Links:
    <div>
      <NavLink activeClassName="active" to={`${match.url}/detail/${ "100"}`}>
        Click me
      </NavLink>
    </div>
  </div>
  <div>
    <Route path={`${match.url}/detail/:code`} render={()=>
      <ProductDetailMore />} />
  </div>
  </> );

当我单击“单击我”时, 100 值会正确显示在我的 ProductDetailMore 组件中,但所有组件都将重新呈现(产品,ProductList,ProductDetail, ProductDetailMore);因此,我的问题是,如何防止父组件[Products,ProductDetail]中的重新渲染?

尤其是,我想避免在ProductList中重新渲染,而不是在Route中?

1 个答案:

答案 0 :(得分:1)

您通常不能真正避免重新渲染,因为react已经决定了哪些组件需要重新渲染。但是,这仅意味着您无法避免重新渲染父组件。使用react dev工具,您可以分析它们为什么要重新渲染(在探查器中是一个选项),并可能找到不必要的原因来重新渲染。

但这是个好消息:

您可以轻松地进行操作,以防止子组件重新渲染。例如“ ProductList”。一种方法是将React.memo HOC直接用于组件的导出或“类别”组件(在静态位置,而不是在render函数中):

const ProductListMemo = React.memo(ProductList)

然后,您在渲染函数中使用“ ProductListMemo”。这样,在渲染组件时,React会预先检查是否有任何道具更改。如果不是,则不重新渲染组件。您的代码虽然不完整。您定义

const productsData = [...]

如果这是在render函数中,则将始终创建一个新数组,即使内容相同,React.memo也将看到一个新数组并重新渲染组件。您必须将数组移到render函数之外,或者必须将其包装在useMemo中(如果您不使用类组件):

const productsData = useMemo(() => [...], []);

这个“ useMemo”钩子也可以用来避免组件的重新渲染,可以使用

{useMemo(() => (<div>
    <ProductList data={productsData} />
</div>), [productsData])}

这样,每个重新渲染的反应都会检查“ productsData”是否发生了更改,然后才重新渲染组件。

所以要知道的重要一点是,例如,如果父组件由于状态更新而重新渲染,它将重新渲染每个子组件。这些也将重新渲染其所有子组件。但是,通过React.memo或useMemo,您可以帮助做出反应,以决定使用以前渲染的组件。