我的应用程序组件中有一个useEffect()
,它检查本地存储中是否有本地存储的用户,如果有,它会用信息更新我的redux状态。这是非常有问题的,因为当一个人去我的路线player/example
时,我的应用程序组件会渲染Player
组件,然后当用户状态从useEffect
更新时,它会再次渲染路线上的Player
组件。因此,运行组件两次,而Player
组件中的任何useEffects
(如获取数据)都会调用数据两次!
是绝对有办法解决这个问题,还是我的功能做错了。它让我发疯
总之,基本上Player
组件会被渲染两次,因为最初应用程序在没有用户的情况下渲染它,当从useEffect中找到用户时,它会再次渲染它,即使您与urlplayer/example
保持在同一页面上
// React
import { useEffect } from 'react'
// Redux
import { useSelector, useDispatch } from 'react-redux'
// React Reducer
import { Routes, Route } from "react-router-dom"
import { loginUser, logoutUser } from './reducers/user';
// Components
import Login from './components/Login';
import Player from './components/Player';
function App() {
console.log("app component")
const dispatch = useDispatch()
const user = useSelector(state => state.user)
useEffect(() => {
const loggedUserJSON = window.localStorage.getItem('loggedUser')
if (loggedUserJSON) {
const user= JSON.parse(loggedUserJSON)
dispatch(loginUser(user))
}
}, [])
// User not logged in
if (!user) {
return (
<Routes>
<Route path="/login" element={<Login/>}/>
<Route path="/" element={<Login/>} />
<Route path="/player/:username" element={<Player/>}/>
</Routes>
)
}
// User logged in
return (
<div>
<h1><button onClick={() => dispatch(logoutUser())}>LOG OUT</button></h1>
<Routes>
<Route path="/login" element={<h1>HOME</h1>}/>
<Route path="/" element={<h1>HOME</h1>} />
<Route path="/player/:username" element={<Player/>}/>
</Routes>
</div>
);
}
export default App;
这是因为App组件中有两个返回语句。在您的情况下,播放器组件没有重新渲染,它只是切换到其他播放器组件,因为您返回了用户在应用程序组件中存在的另一个元素。
为了解决这个问题,无论用户是否存在,都必须返回一个元素。
这是我的密码。
function App() {
console.log("app component")
const dispatch = useDispatch()
const user = useSelector(state => state.user)
useEffect(() => {
const loggedUserJSON = window.localStorage.getItem('loggedUser')
if (loggedUserJSON) {
const user = JSON.parse(loggedUserJSON)
dispatch(loginUser(user))
}
}, [])
return (
<div>
{user && <h1><button onClick={() => dispatch(logoutUser())}>LOG OUT</button></h1>}
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/" element={<Login />} />
<Route path="/player/:username" element={<Player />} />
</Routes>
</div>
);
}
在这段代码中,Route组件是同一个组件,而不是新组件,道具也没有改变,所以不会重新渲染。您必须实现对用户存在的登录组件视图的更改,因为此逻辑属于登录组件,而不是应用程序组件。