【问题标题】:Prevent React component re render when route change路由更改时防止 React 组件重新渲染
【发布时间】:2021-08-13 07:40:40
【问题描述】:

我正在使用 react-router-dom。

假设我有 2 个页面,例如主页和个人资料页面。两个页面都有一个名为 Header 的组件。

在 Header 组件中,使用 useEffect React Hook 我在后端服务器上调用 fetch 请求并获取登录的用户数据。 API返回用户名、头像等(这不是问题)

事情就是这样。当我从“主页”跳转到“个人资料页面”时,Header 组件会重新渲染并将请求再次发送到服务器。每次我从主页跳转到个人资料页面或个人资料页面到主页时都会发生这种情况。并且 Header 上显示的数据会一直加载,直到获取请求成功。

我想要 Youtube 之类的东西。

标题组件

import {useState , useEffect} from 'react'

import Logo from './imgs/logo.png'
import {Link} from 'react-router-dom'

import { FaArrowRight , FaServicestack , FaFirstOrder} from "react-icons/fa";
import { BsPersonCheck , AiOutlineContacts } from "react-icons/all";


const ShowOrHideNav = ()=>{
    var nav = document.getElementById('NavBarSpingbuck')
    nav.classList.toggle('hidden')
}


const Header = () =>{
    const [loggedIn , setLoggedIn] = useState(false)
    const [user_data , setUserData] = useState(undefined)

    const Logout = () =>{
        localStorage.removeItem('sb_auth_token')
        UpdateHeader()
    }

    const UpdateHeader = () =>{
        const auth_token = localStorage.getItem('sb_auth_token')
        if(auth_token){
            console.log('sending request')
            fetch(
                'https://dummy_API_URL.dummy_domain.com/authentication/user/',
                {
                    headers:{
                        Authorization : 'Token ' + auth_token,
                    },
                }
            )
            .then(response => response.json())
            .then(resp_data =>{
                if(resp_data.status == 200){
                    setUserData(resp_data.data)
                }
            })
            .catch(error =>{
                console.log(error)
                console.log('error')
            })
            setLoggedIn(true)
        }
        else{
            setLoggedIn(false)
        }
    }

    useEffect(()=>{
        UpdateHeader()
        
    } , [])
    return(
        <div className=' fixed top-0 z-50 w-full shadow bg-black bg-opacity-75 px-5' style={{backdropFilter:'blur(18px)'}}>
            <div className='container py-2 flex items-center justify-between mx-auto relative'>
                <div className='w-8 h-8 md:hidden flex flex-col justify-evenly items-end cursor-pointer group ' onClick={ShowOrHideNav}>
                    <span className='w-2 h-1 bg-white block rounded-full transition-all delay-150 duration-300 group-hover:w-8'></span>
                    <span className='w-4 h-1 bg-white block rounded-full transition-all duration-300 group-hover:w-8'></span>
                    <span className='w-8 h-1 bg-white block rounded-full '></span>
                </div>
                <div>
                    <Link to='/'>
                        <img src={Logo} className='w-32 ' />
                    </Link>
                </div>
                <div className='px-5'>
                    <ul className='items-center hidden p-4 md:p-0 md:flex absolute md:relative top-full md:top-0 w-full md:w-auto z-50 left-0 bg-white md:bg-transparent rounded-lg md:rounded-none transition-all duration-300' style={{animationIterationCount:1}} id='NavBarSpingbuck'>
                        <li className='hover:scale-110 duration-150 transform px-4 mb-4 md:mb-0' >
                            <Link className='flex flex-col items-center text-gray-800 md:text-white'>
                                <p>Jobs</p>
                            </Link>
                        </li>
                        <li className='hover:scale-110 duration-150 transform px-4 mb-4 md:mb-0' >
                            <Link className='flex flex-col items-center text-gray-800 md:text-white'>
                                <p>Services</p>
                            </Link>
                        </li>
                        <li className='hover:scale-110 duration-150 transform px-4 mb-4 md:mb-0' >
                            <Link className='flex flex-col items-center text-gray-800 md:text-white'>
                                <p>Place Order</p>
                            </Link>
                        </li>
                        <li className='hover:scale-110 duration-150 transform px-4 mb-4 md:mb-0' >
                            <Link className='flex flex-col items-center text-gray-800 md:text-white'>
                                <p>About</p>
                            </Link>
                        </li>
                        <li className='hover:scale-110 duration-150 transform px-4 mb-4 md:mb-0' >
                            <Link className='flex flex-col items-center text-gray-800 md:text-white'>
                                <p>Contact</p>
                            </Link>
                        </li>
                    </ul>
                </div>
                <div className='account_bar'>
                    {
                        loggedIn?
                        <div className='flex items-center cursor-pointer group relative py-1'>
                            <div className='mr-3 rounded-full w-10 h-10 bg-center bg-cover' style={{backgroundImage:'url(https://pixinvent.com/materialize-material-design-admin-template/app-assets/images/user/12.jpg)'}}>
    
                            </div>
                            {
                                user_data && user_data.username ?
                                <p className='text-white'>{user_data.username}</p>: <p className='text-white'>User</p>

                            }
                            <div className='bg-white rounded-md py-2 w-28 absolute top-full shadow-2xl hidden group-hover:block'>
                                <ul>
                                    <li className='px-2 py-1 hover:bg-blue-100'>
                                        <Link className='block' to='/profile/' >Profile</Link>
                                    </li>
                                    <li className='px-2 py-1 hover:bg-blue-100' onClick={()=>{Logout()}}>
                                        Logout
                                    </li>
                                </ul>
                            </div>
                        </div>
                            

                        :
                        <Link to='/authentication/login/' >
                            <div className='bg-yellow-600 py-0.5 px-2 rounded flex items-center justify-center hover:bg-yellow-700 transition-all duration-300'>
                                <p className='text-white pr-1'>Sign in</p>
                                <FaArrowRight className='text-white text-sm' />
                            </div>
                        </Link>
                    }
                </div>
                
            </div>
        </div>
    )
}

export default Header 

【问题讨论】:

    标签: reactjs routes react-router-dom react-component


    【解决方案1】:

    提取Header 组件并将其与Switch 组件放在同一级别。

    <Router>
      <Header />
      <Switch>
        <Route path="/">
          <Home />
        </Route>
        <Route path="/profile">
          <Profile />
        </Route>
      </Switch>
    </Router>
    

    【讨论】:

      【解决方案2】:

      您可以在自己的路由上渲染您的Header 组件,与渲染主页或个人资料页面的路由分开。使用您希望标题组件的Route 匹配的路径数组。假设“/”是您的主页,那么您可能还想指定 exact 属性,因此“/”与您拥有的 每个 路径不匹配。当然,这一切还假设标题组件在每个主页和个人资料页面的页面上的所有其他内容之前呈现。

      例子:

      <Router>
        <Route exact path={["/profile", "/"]} component={Header} />
        <Switch>
          <Route path="/profile" component={ProfilePage} />
          <Route path="/" component={HomePage" />
        </Switch>
      </Router>
      

      【讨论】:

      • 感谢您回答我的问题,但它并没有解决我的问题。 [链接]springbuck.herokuapp.com),这是我网站的链接。请查看这些凭据。电子邮件 = dummy@gmail.com 和密码 = dummy
      • 登录时,请在主页和个人资料页面之间导航。 (悬停头像时找到个人资料页面链接),请注意标题行为,特别是标题右侧部分
      • @ZeevhYOrg。我相信这个解决方案总体上是有效的,并且应该让你接近你正在寻找的东西。您能否更新您的问题以包含Minimal, Complete, and Reproducible Code Example,以便更轻松地查看您正在处理的内容?
      • 我用 Header 组件代码更新了问题。希望这有助于理解,
      • @ZeevhYOrg。老实说,更重要的代码是 where/what 渲染 Header 组件,因为这是安装/重新安装它的内容。
      猜你喜欢
      • 1970-01-01
      • 2019-06-04
      • 2021-11-16
      • 1970-01-01
      • 2020-01-02
      • 2022-11-12
      • 1970-01-01
      • 2020-06-18
      • 1970-01-01
      相关资源
      最近更新 更多