React Redux无法获取更新后的user状态值,求解决方案
解决React+Redux+Firebase登录后无法获取更新user值的问题
核心问题
你当前的代码中,登录成功后仅将用户信息存入localStorage,但没有同步更新Redux Store中的user状态。Redux的状态只有通过触发reducer更新才会通知组件重新渲染,因此Index.jsx中通过useSelector获取的始终是初始化时从localStorage读取的旧值。
解决方案步骤
1. 在Redux Slice中添加更新用户状态的Reducer
修改BooksSlice.jsx,新增一个setUser的reducer函数,用于更新Store中的user值:
import { createSlice } from '@reduxjs/toolkit'; import { v4 as uuidv4 } from 'uuid'; const initialBooks = { books: [ { id: uuidv4(), title: 'Ordinary Differential Equation', author: 'Prof. Md. Abu Yousuf', }, { id: uuidv4(), title: 'CSE Kit', author: 'Gyan Bitan' }, ], user: JSON.parse(localStorage.getItem('user')) || null, }; export const BooksSlice = createSlice({ name: 'books', initialState: initialBooks, reducers: { showBooks: state => state, addBook: (state, action) => { state.books.push(action.payload); }, deleteBook: (state, action) => { const id = action.payload; state.books = state.books.filter(book => book.id !== id); }, updateBook: (state, action) => { const { id, title, author } = action.payload; const isBookExist = state.books.find(book => book.id === id); // 替换filter为find,更高效 if (isBookExist) { isBookExist.title = title; isBookExist.author = author; } }, // 新增更新用户的reducer setUser: (state, action) => { state.user = action.payload; }, }, }); // 导出新增的setUser action export const { showBooks, addBook, deleteBook, updateBook, setUser } = BooksSlice.actions; export default BooksSlice.reducer;
2. 在Login组件中触发更新Redux状态的Action
修改Login.jsx,导入useDispatch和setUser,在登录成功后dispatch这个action来同步更新Redux的user状态:
import React, { useState } from 'react'; import { signInWithEmailAndPassword } from 'firebase/auth'; import { auth } from '../firebase/firebase'; import { useNavigate } from 'react-router-dom'; // 新增导入 import { useDispatch } from 'react-redux'; import { setUser } from '../path/to/BooksSlice'; // 替换为你的实际路径 const Login = () => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(false); const navigate = useNavigate(); // 初始化dispatch const dispatch = useDispatch(); // Login Handler Function const loginHandler = event => { event.preventDefault(); signInWithEmailAndPassword(auth, email, password) .then(userCredential => { // Signed in const user = userCredential.user; localStorage.setItem('user', JSON.stringify(user)); // 新增:dispatch action更新Redux中的user状态 dispatch(setUser(user)); navigate('/show-books', { replace: true }); }) .catch(error => { setError(true); }); }; // 其余代码不变... }; export default Login;
3. (可选)监听Firebase Auth状态变化,处理自动登录/登出
为了处理页面刷新、用户主动登出等场景,建议在Index.jsx中添加Firebase Auth状态监听,自动同步到Redux:
import React, { useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import ShowBooks from '../pages/ShowBooks'; import AddBook from '../pages/AddBook'; import EditBook from '../pages/EditBook'; import Login from '../pages/Login'; import Navbar from '../components/Navbar'; // 新增导入 import { auth } from '../firebase/firebase'; import { setUser } from '../path/to/BooksSlice'; // 替换为实际路径 const Index = () => { const { user } = useSelector(state => state.case); const dispatch = useDispatch(); // 监听Auth状态变化 useEffect(() => { const unsubscribe = auth.onAuthStateChanged(authUser => { if (authUser) { localStorage.setItem('user', JSON.stringify(authUser)); dispatch(setUser(authUser)); } else { localStorage.removeItem('user'); dispatch(setUser(null)); } }); // 组件卸载时取消监听 return () => unsubscribe(); }, [dispatch]); let routes; if (user === null || user === undefined) { routes = ( <Routes> <Route path="/login" element={<Login />} /> <Route path="*" element={<Navigate to="/login" replace={true} />} /> </Routes> ); } else { routes = ( <> <Navbar /> <Routes> <Route path="/" element={<ShowBooks />} /> <Route path="/show-books" element={<ShowBooks />} /> <Route path="/add-book" element={<AddBook />} /> <Route path="/edit-book" element={<EditBook />} /> <Route path="/login" element={<Login />} /> <Route path="*" element={<Navigate to="/" replace={true} />} /> </Routes> </> ); } return <BrowserRouter>{routes}</BrowserRouter>; }; export default Index;
说明
完成以上修改后,登录成功时Redux Store的user状态会被更新,Index.jsx通过useSelector能实时获取到最新的用户信息,从而正确渲染对应的路由。
内容的提问来源于stack exchange,提问作者Mahbubul Hasan
相关产品推荐
相关产品推荐

