更新状态后防止顶部滚动

问题描述 投票:0回答:1

嗨,我在每次渲染后滚动到首页时遇到问题。 在我的 Root 组件中,当我从 Redux Store 获取对象项数组时。 我在三个子数组上过滤 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>
  );

  };
reactjs redux react-redux
1个回答
2
投票

为什么每次动作分派到 redux store 时都会进行 React 渲染

因为您正在订阅整个 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路由器文档

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

© www.soinside.com 2019 - 2024. All rights reserved.