0

嗨,我在每次渲染后滚动到首页时遇到问题。在我的 Root 组件中,当我从Redux Store获取 Array of objects items 时。我在三个 subsArray 上过滤 mainArray,例如:Hot、Favorite、Regular,然后在特定路线上渲染它们中的每一个。每次更新 mainArray 时都会运行过滤器函数:喜欢评分上升和下降或设置收藏夹将被标记。
问题是,为什么每次将动作分派到 redux 存储时都做出反应渲染(我认为 redux 会导致这种情况,我猜)以及如何防止这种情况发生。请给我一个提示,我挣扎了一段时间......

function Root() {
  const state = useSelector((state) => state);
  const { mainList: list } = state;

  const [regularList, setRegularList] = useState([]);
  const [hotList, setHotList] = useState([]);
  const [favoriteList, setFavoriteList] = useState([]);

const dispatch = useDispatch();

  const handleVote = (e) => {
    const currentId = Number(e.nativeEvent.path[3].id);
    const name = e.currentTarget.dataset.name;

    dispatch(listActions.vote(currentId, name));
  };

  const handleSetFave = (e) => {
    const currentId = Number(e.nativeEvent.path[3].id);
    dispatch(listActions.setFave(currentId));

const setArrays = (arr) => {
    const regularArr = arr.filter((meme) => meme.upvote - meme.downvote <= 5);
    const hotArr = arr.filter((meme) => meme.upvote - meme.downvote > 5);
    const favoriteArr = arr.filter((meme) => meme.favorite);

    setRegularList([...regularArr]);
    setHotList([...hotArr]);
    setFavoriteList([...favoriteArr]);
};

useEffect(() => {
    window.localStorage.getItem("mainList") &&
      dispatch(
        listActions.setMainList(
          JSON.parse(window.localStorage.getItem("mainList"))
        )
      );
  }, []);

  useEffect(() => {
    setArrays(list);
    list.length > 0 &&
      window.localStorage.setItem("mainList", JSON.stringify(list));
  }, [list]);

return (
    <div className={styles.App}>
      <Router>
        <Navigation />
        <Route path="/" component={FormView} exact />
        <Route
          path="/regular"
          component={() => (
            <MemesView
              list={regularList}
              handleVote={handleVote}
              handleSetFave={handleSetFave}
            />
          )}
        />
        <Route
          path="/hot"
          component={() => (
            <MemesView
              list={hotList}
              handleVote={handleVote}
              handleSetFave={handleSetFave}
            />
          )}
        />
        <Route
          path="/favorite"
          component={() => (
            <MemesView
              list={favoriteList}
              handleVote={handleVote}
              handleSetFave={handleSetFave}
            />
          )}
        />
      </Router>
    </div>
  );

  };
4

1 回答 1

1

为什么每次将动作分派到redux商店时都做出反应

因为您订阅了整个 redux 状态(通过使用useSelector((state) => state);),所以请记住,每次调度操作时,redux 都会计算一个新状态。

所以你不应该写,const state = useSelector(state => state);否则你的组件将在每次调度动作时重新呈现。相反,您必须选择您感兴趣的状态部分。

我可以从您的代码中推断出您希望在每次更改时都收到通知mainList,因此您可以编写:

const list = useSelector(state => state.mainList);

您可以通过阅读文档获取更多信息

默认情况下,useSelector() 将在调度操作后运行选择器函数时对选定值进行引用相等比较,并且仅在选定值更改时才会导致组件重新渲染

基本上,scroll to top page您遇到的问题也可能来自对Route组件的不当使用。

尝试使用这个

<Route path="/regular">
  <MemesView
    list={regularList}
    handleVote={handleVote}
    handleSetFave={handleSetFave}
  />
</Route>

代替

<Route path="/regular"
       component={() => (
         <MemesView
           list={regularList}
           handleVote={handleVote}
           handleSetFave={handleSetFave}
         />
       )}
/>

不要忘记更新/hot/favorite路由。

您可以阅读反应路由器文档

当你使用组件(而不是渲染或子,下面)时,路由器使用 React.createElement 从给定组件创建一个新的 React 元素。这意味着如果您为组件属性提供内联函数,您将在每次渲染时创建一个新组件。这会导致现有组件卸载和新组件安装,而不是仅仅更新现有组件。使用内联函数进行内联渲染时,请使用 render 或 children 道具(如下)。

于 2021-06-26T14:04:54.947 回答