【问题标题】:How to prevent React component from re-rendering when I am changing routes?更改路由时如何防止 React 组件重新渲染?
【发布时间】:2021-12-15 19:57:19
【问题描述】:

我有 React 组件:allUsersList 和 userDetail。在第一个中,我正在获取所有用户并显示它们,通过单击每个用户,我正在更改路线并转到第二个组件,但是当我单击箭头返回浏览器时,第一个组件开始获取数据并再次重新渲染.你能告诉我如何防止它进行额外的重新渲染吗?

这是 AllUsers 组件:

import React, {useEffect, useMemo} from 'react';
import { Link } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import {setAllUsers, setLoading, setPage} from '../redux/actions/actions';
import User from './User';
import '../styles/AllUsersList.css';

const AllUsersList = () => {
    const allUsers = useSelector(state => state.setAllUsersReducer);
    const page = useSelector(state => state.setPageReducer);
    const loading = useSelector(state => state.setLoadingReducer);
    const dispatch = useDispatch();
  

    const fetchAllUsers = () => {
       fetch(`${url}/${page}/15`)
            .then(res => res.json())
            .then(data => {
                dispatch(setAllUsers(data.list));
            })
            .catch(err => console.log('Error message: ', err))
    }

    useEffect(() => {
      fetchAllUsers();
    }, [page])

    const handleScroll = () => {
        dispatch(setPage());
    }

    window.onscroll = function () {
        if(window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight) {
            handleScroll();
        }
    }


    return (
        <div className="allUsersList">
            {
                allUsers ? (
                    allUsers.map((user, index) => (
                        <Link key={user.id} to={`/user/${user.id}`}>
                            <User name={user.name} lastName={user.lastName} prefix={user.prefix} title={user.title} img={user.imageUrl}/>
                        </Link>
                    ))
                ) : (
                    <div> Loading... </div>
                )
            }
        </div>
    )
}

export default AllUsersList;

这是 UserDetails 组件:

import React, {useEffect} from 'react';
import {useParams} from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { setSelectedUser, removeUser, setSelectedUsersHistory } from '../redux/actions/actions';

export const UserDetails = () => {
    const selectedUser = useSelector(state => state.setSelectedUserReducer);
    const selectedUsersHistory = useSelector(state => state.setSelectedUsersHistoryReducer);
    const dispatch = useDispatch();
    const {userId} = useParams();
    const fetchUserDetails = () => {
        fetch(`${url}/${userId}`)
            .then(res => res.json())
            .then(data => {
                 dispatch(setSelectedUser(data));
              }
            )
            .catch(err => console.log('Error message: ', err))
    }

    useEffect(() => {
        if(userId && userId!=='') fetchUserDetails();
        
        return () => {
            dispatch(removeUser())
        }
    }, [userId])


    return (
        <div className="userDetails">
            {
                Object.keys(selectedUser).length === 0 ? (
                    <div>Loading...</div>
                ) : (
                    <div>{selectedUser.name}</div>
                )
            }
        </div>
    )
}

export default UserDetails;

这里是带有路由的 App,js:

import React from 'react';
import AllUsersList from './components/AllUsersList';
import UserDetails from './components/UserDetails';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';

function App() {

  return (
    <div className="App">
      <Router>
        <Switch>
          <Route path="/" exact component={AllUsersList} />
          <Route path="/user/:userId" exact component={UserDetails} />
        </Switch>
      </Router>
 
    </div>
  );
}

export default App;

【问题讨论】:

  • 在我看来,如果您已经获取了allUsers,那么您不想再次获取......但allUsers 似乎依赖于这个page 值也从redux 状态中选择。我想您还应该缓存当前allUsers 数组所关联的页面值,并且仅在页面值实际上与以前不同时才重新获取。
  • 我认为我已经这样做了,但显然我错了,但不知道具体在哪里。在 useEffect 中,我从逻辑上传递了依赖项 [page],它应该仅在页面更改的情况下获取,但是是的,我仍然在某些部分错了,我无法找到确切的部分。
  • 当您从“/”导航到特定页面时,我相信AllUsersList 已卸载,当您导航回“/”时,我相信它已重新安装。
  • 当我从“/”导航到不同的组件时,我认为数据已经重新获取,因为实际上所有用户都有一个相同的链接并自动生成图片的图像源链接,所以当我要从“/”到不同的组件图像正在发生变化,这仅在从“/”导航后已经获取数据的情况下才会发生
  • 抱歉,这有点难以理解。是的,数据是在“/”上获取的,所以当转到不同的组件时,它已经被获取了。现在的问题不是导航 back 到“/”会触发另一个数据获取(相同数据)吗?这不是你要问的问题吗?

标签: javascript reactjs react-router-dom


【解决方案1】:

你试过 useMemo() 吗? https://reactjs.org/docs/hooks-reference.html#usememo

一旦呈现,它就会“记忆”您的页面。这不是每次渲染的保证,但根据我的经验,它通常确实有效。

【讨论】:

  • Michael,你的意思是对整个组件都使用 useMemo() 吗?
  • 在组件中返回 JSX 之前,将更改状态的函数调用放在 useEffect() 块中实际上可能会更好。它看起来像你做的。因此,为了防止重新获取,我使用 graphQL 并设置 fetch-policy 以重新使用缓存。 medium.com/@galen.corey/…。恐怕不知道如何利用 graphQL 之外的缓存。
  • 好的,我会深入挖掘,非常感谢您的关注和帮助!
猜你喜欢
  • 2021-08-13
  • 2019-06-04
  • 2021-11-16
  • 2022-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-05
相关资源
最近更新 更多