嗨,我在每次渲染后滚动到首页时遇到问题。
在我的 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>
);
};
为什么每次动作分派到 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 属性(如下)。