【发布时间】:2021-10-20 20:14:22
【问题描述】:
我正在使用 react-router 作为不同页面的链接。一切正常,但是,一旦我刷新页面,它会进入登录页面片刻,然后会返回主页。更糟糕的是,如果我去管理页面,刷新页面会将用户引导到登录页面,但是,用户仍然登录并且只显示登录页面。我也在使用 Firebase Firestore 和 firebase 身份验证。
app.js
const App = (props) => {
const { setCurrentUser, currentUser } = props;
const admin = checkUserAdmin(currentUser);
console.log(admin);
useEffect(() => {
const authListener = auth.onAuthStateChanged(async (userAuth) => {
if (userAuth) {
const userRef = await handleUserProfile(userAuth);
userRef.onSnapshot((snapshot) => {
setCurrentUser({
id: snapshot.id,
...snapshot.data(),
});
});
}
setCurrentUser(userAuth);
});
return () => {
authListener();
};
}, []);
return (
<div className="App">
<Switch>
<Route
exact
path="/"
render={() => (
<MainLayout>
<Homepage />
</MainLayout>
)}
/>
<Route
exact
path="/login"
render={() => (
<MainLayout>
<LoginPage />
</MainLayout>
)}
/>
<Route
exact
path="/profile"
render={() => (
<WithAuth>
<MainLayout>
<ProfilePage />
</MainLayout>
</WithAuth>
)}
/>
<Route
exact
path="/admin"
render={() => (
<WithAdmin>
<AdminHome />
</WithAdmin>
)}
/>
</Switch>
</div>
);
};
const mapStateToProps = ({ user }) => ({
currentUser: user.currentUser,
});
const mapDispatchToProps = (dispatch) => ({
setCurrentUser: (user) => dispatch(setCurrentUser(user)),
});
export default connect(mapStateToProps, mapDispatchToProps)(App);
withAuth - 限制页面的用户。如果 currentUser 是访客用户,它会将用户定向到登录页面。
import { useAuth } from "./../custom-hooks";
import { withRouter } from "react-router-dom";
const WithAuth = (props) => useAuth(props) && props.children;
export default withRouter(WithAuth);
useAuth - 限制页面的用户。如果 currentUser 是访客用户,它会将用户定向到登录页面。
const mapState = ({ user }) => ({
currentUser: user.currentUser,
});
const useAuth = (props) => {
const { currentUser } = useSelector(mapState);
useEffect(() => {
if (!currentUser) {
props.history.push("/login");
}
}, [currentUser]);
return currentUser;
};
export default useAuth;
withAdmin - 只有管理员可以访问的页面
import { useAdmin } from "../../custom-hooks";
const WithAdmin = (props) => useAdmin(props) && props.children;
export default WithAdmin;
useAdmin - 只有管理员可以访问的页面。如果用户不是管理员,它会将用户定向到登录页面。
const mapState = ({ user }) => ({
currentUser: user.currentUser,
});
const useAdmin = (props) => {
const { currentUser } = useSelector(mapState);
const history = useHistory();
useEffect(() => {
if (!checkUserAdmin(currentUser)) {
history.push("/login");
}
}, [currentUser]);
return currentUser;
};
export default useAdmin;
下面是我的 index.js
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
减速机: 用户类型:
const userTypes = {
SET_CURRENT_USER: "SET_CURRENT_USER",
};
export default userTypes;
用户操作:
import userTypes from "./user.types";
export const setCurrentUser = (user) => ({
type: userTypes.SET_CURRENT_USER,
payload: user,
});
userReducer:
import userTypes from "./user.types";
const INITIAL_STATE = {
currentUser: null,
};
const userReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case userTypes.SET_CURRENT_USER:
return {
...state,
currentUser: action.payload,
};
default:
return state;
}
};
export default userReducer;
rootReducer:
import { combineReducers } from "redux";
import userReducer from "./user/user.reducer";
export default combineReducers({
user: userReducer,
});
store.js
import { createStore, applyMiddleware } from "redux";
import logger from "redux-logger";
import rootReducer from "./rootReducer";
export const middlewares = [logger];
export const store = createStore(rootReducer, applyMiddleware(...middlewares));
export default store;
checkUserAdmin.js
export const checkUserAdmin = (currentUser) => {
if (!currentUser || !Array.isArray(currentUser.roles)) return false;
const { roles } = currentUser;
if (roles.includes("admin")) return true;
return false;
};
【问题讨论】:
-
只是一个次要的、无关的、关于命名约定的观点......名称如
WithAdmin,或任何带有with-前缀的函数,人们会期望它是一个高阶组件一个包装组件。话虽这么说,您遇到的问题是您的 redux 存储存在于内存中,因此当页面重新加载时,您的应用程序也是如此,并且可能需要一些时间来重新填充您的user状态切片。在这些情况下,您需要使用第三种“不确定”或未决状态来表示不是关于访问的一种状态或另一种状态。 -
我忘了说是的,它是一个高阶组件。那些 withAuth 和 withAdmin。
-
抱歉,我是在指出这些 不是 HOC,但您已将它们命名为原来的样子。
-
有什么办法可以解决吗?
-
您能否将您的
user减速器代码添加到您的问题中?正如我所说,我认为这里的解决方案是使用“待处理”状态,而不是立即决定用户是否应该访问资源或被退回路由。
标签: javascript reactjs firebase react-redux react-router