store/index.js
import { configureStore } from "@reduxjs/toolkit";
import rootReducer from "../reducers/index";
const store = configureStore({
reducer: {
user: rootReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}),
});
export default store;
userSlice.js
import { createSlice } from "@reduxjs/toolkit";
export const INITIAL_STATE = {
name: "Hello World",
email: "",
photo: "",
};
export const userSlice = createSlice({
name: "user",
initialState: INITIAL_STATE,
reducers: {
setUserLoginDetails: (state, action) => {
console.log("Initial", state.name);
state.name = action.payload.name;
state.email = action.payload.email;
state.photo = action.payload.photo;
console.log("Updated", state.name);
},
setSignOutState: (state) => {
state.name = null;
state.email = null;
state.photo = null;
},
},
});
export const { setUserLoginDetails, setSignOutState } = userSlice.actions;
export const selectUserName = (state) => state.user.name;
export const selectUserEmail = (state) => state.user.email;
export const selectUserPhoto = (state) => state.user.photo;
export default userSlice.reducer;
AuthContext.js
import React, { useContext, createContext, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
GoogleAuthProvider,
signInWithPopup,
signInWithRedirect,
signOut,
onAuthStateChanged,
} from "firebase/auth";
import { auth } from "../firebase";
import { setUserLoginDetails, selectUserName } from "../reducers/userSlice";
import store from "../store/index";
const AuthContext = createContext();
export const AuthContextProvider = ({ children }) => {
const dispatch = useDispatch();
const username = useSelector(selectUserName);
const googleSignIn = () => {
const provider = new GoogleAuthProvider();
signInWithPopup(auth, provider)
.then((result) => {
console.log("Check Initial Store", store.getState());
console.log("Check Initial Name", username);
setUser(result.user);
console.log("Check Updated Store", store.getState());
console.log("Check Updated Name", username);
})
.catch((e) => {
const eCode = e.code;
const eMessage = e.message;
const eEmail = e.email;
const eCredential = e.credential;
});
};
const setUser = (user) => {
dispatch(
setUserLoginDetails({
name: user.displayName,
email: user.email,
photo: user.photoURL,
})
);
};
return (
<AuthContext.Provider value={{ googleSignIn, username }}>
{children}
</AuthContext.Provider>
);
};
export default AuthContext;
export const UserAuth = () => {
return useContext(AuthContext);
};
App.js
import {
BrowserRouter as Router,
Route,
Routes,
Navigate,
} from "react-router-dom";
import "./App.css";
import Header from "./components/Header";
import Home from "./components/Home";
import Login from "./components/Login";
import { AuthContextProvider, UserAuth } from "./context/AuthContext";
import { useEffect } from "react";
//import { useSelector } from "react-redux";
//import { selectUserName } from "./reducers/userSlice";
import { onAuthStateChanged } from "firebase/auth";
function App(props) {
const { username } = UserAuth();
useEffect(() => {
//if (username != null) {
console.log("User name is", username);
//}
}, [username]);
return (
<div className="App">
<AuthContextProvider>
<Router>
<Routes>
<Route
exact
path="/"
element={/*username ? <Navigate to="/home" /> : */<Login />}
/>
<Route
path="/home"
element={
/*!username ? (
<Navigate to="/" />
) :*/ (
<>
<Header />
<Home />
</>
)
}
/>
{/*<Route path="/redirect" element={<Navigate to="/home" />} />*/}
</Routes>
</Router>
</AuthContextProvider>
</div>
);
}
export default App;
问题出在AuthContext.js
,我试图通过useSelector(SelectUserName)
从userSlice.js中选择当前用户名,即(state) => state.user.name
。console.log
在附件中输出了日志:
编辑:我忘了添加我的reducers/index.js
,所以在这里你去。
reducers/index.js
import { combineReducers } from "redux";
import userReducer from "./userSlice";
const rootReducer = combineReducers({
userState: userReducer,
});
export default rootReducer;
非常感谢大家的回应。我已经尝试在userSlice.js
下转换:
从selectUserName = (state) => state.user.name;
到selectUserName = (state) => state.user.userState.name;
而且我能够得到正确的username
,而不是unknown
。任何进一步的建议将不胜感激。
2条答案
按热度按时间np8igboo1#
根据您在帖子中包含的屏幕截图,很明显Redux商店具有以下结构:
换句话说,要选择
name
状态,它不是***state.user.name
,而是state.user.userState.name
。您可以修复选择器函数,以便使用正确的路径选择适当的状态。
示例:
更有可能的情况是,在导出/合并到
rootReducer
时,您无意中“嵌套”了这个userSlice.reducer
。看起来像是在创建rootReducer
时合并/合并了一个userState
reducer,然后在配置存储时将根reducer合并为user
。根reducer和store配置应该看起来类似于以下基于您当前的选择器函数:
../userSlice.js选择器
../reducers/index.js
store/index.js
a9wyjsp72#
您的商店设置的这一部分可能是问题所在:
rootReducer
到底是什么?看起来你要么想做这样的事情:或者像这样为每个切片设置缩减器:
https://redux-toolkit.js.org/tutorials/quick-start#add-slice-reducers-to-the-store