【问题标题】:Multiple useEffect React.useEffect has missing dependencies多个 useEffect React.useEffect 缺少依赖项
【发布时间】:2020-01-06 11:14:28
【问题描述】:

我有一个 Products 组件,它显示一个类别的产品。 CategoryId 取自路由参数,然后用户可以对产品进行分页。所以有 2 个 useEffect 一个是 categoryId 改变的时候,一个是当前页码改变的时候。如果我使用一个具有两个依赖项(categoryId 和 currentPage)的效果,我找不到将当前页码重置为 1 的方法。(当用户处于类别 1 并转到 2 页时,我想重置页码当类别发生变化时)

import React from "react";
import {
  useProductState,
  useProductDispatch
} from "../contexts/product.context";

const Products = props => {
  const categoryId = +props.match.params.id;

  const { categoryProducts, totalCount } = useProductState();
  const [currentPage, setCurrentPage] = React.useState(1);

  const dispatch = useProductDispatch();

  const pageSize = 2;
  const pageCount = Math.ceil(+totalCount / pageSize);

  React.useEffect(() => {
    setCurrentPage(1);
    dispatch({
      type: "getPaginatedCategoryProducts",
      payload: {
        categoryId,
        pageSize,
        pageNumber: currentPage
      }
    });
  }, [categoryId]);

  React.useEffect(() => {
    dispatch({
      type: "getPaginatedCategoryProducts",
      payload: {
        categoryId,
        pageSize,
        pageNumber: currentPage
      }
    });
  }, [currentPage]);

  const changePage = page => {
    setCurrentPage(page);
  };

  return (
    <div>
      <h1>Category {categoryId}</h1>
      {categoryProducts &&
        categoryProducts.map(p => <div key={p.id}>{p.name}</div>)}
      {pageCount > 0 &&
        Array.from({ length: pageCount }).map((p, index) => {
          return (
            <button key={index + 1} onClick={() => changePage(index + 1)}>
              {index + 1}
            </button>
          );
        })}
      <br />
      currentPage: {currentPage}
    </div>
  );
};

export default Products;

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    你有两个效果:

    1.当categoryId更改时,将当前页面设置为1:

      React.useEffect(() => {
        setCurrentPage(1);
      }, [categoryId]);
    

    2.当categoryIdcurrentPage发生变化时获取新数据:

      React.useEffect(() => {
        dispatch({
          type: "getPaginatedCategoryProducts",
          payload: {
            categoryId,
            pageSize,
            pageNumber: currentPage
          }
        });
      }, [currentPage, categoryId, dispatch]);
    

    https://codesandbox.io/s/amazing-cartwright-jdg9j

    【讨论】:

    • 我刚刚注意到,当我们在类别一的第二页,点击类别二时,useEffect 运行了两次。有什么办法可以防止这种情况发生吗?
    • 是的,你可以在路由改变时强制组件重置状态:&lt;Route path="/products/:id" render={(props) =&gt; &lt;Products key={props.match.params.id} {...props} /&gt;} /&gt;
    • 我的意思是 useEffect with dispatch 为第 1 页和第 2 页运行两次,因为当 categoryId 更改时,它会将 currentPage 重置为 1,这再次使 useEffect 运行。我在这里看不到与路由有任何关系,如果我不明白,请见谅。
    • 在我提供的代码中,当类别 Id 更改时,我更改了 key 属性,这将强制 Products 组件重置状态(currentPage = 1),因此 useEffect 不会触发两次,试试看;)
    • 我认为它没有特定的名称^^
    【解决方案2】:

    我认为您可以像为页面所做的那样将类别保持在组件的本地状态。然后你可以检查本地状态是否与 Redux 状态匹配。如果没有,您可以重置页码并设置新类别,或者仅在需要时更改页码。另一个 useEffect 可能不适用于类别更改,因为它不是本地状态更改,并且 useEffect 仅在本地状态更改时触发。这是一个可能有帮助的例子

          React.useEffect(() => {
            if(categoryId!==currentCategory){
            dispatch({
               type: "getPaginatedCategoryProducts",
               payload: {
               categoryId,
               pageSize,
               pageNumber: 1
            }
            });
            }
            else{
            dispatch({
               type: "getPaginatedCategoryProducts",
               payload: {
               categoryId,
               pageSize,
               pageNumber: currentPage
            }
            });
            }
            }, [categoryId,currentPage]);
    

    希望你能理解,答案对你有帮助。

    【讨论】:

    • 谢谢比拉尔,接受的答案似乎是正确的。
    • 是的,你是对的。如果您能投票,我将不胜感激。谢谢!
    猜你喜欢
    • 2020-01-18
    • 2020-03-24
    • 2021-02-23
    • 2021-08-19
    • 2020-10-26
    • 2019-10-24
    • 2020-03-07
    相关资源
    最近更新 更多