我有一个带有 Redux 的 React 应用程序(Vite),用于全局状态管理。我在 Redux 商店中有一个名为
auth
的布尔值全局状态,当用户正确注册应用程序或登录应用程序时,它会通过调度程序进行更新。我可以看到 Redux 开发工具中正在发生这种状态变化。但是当该身份验证的状态为 true 时,组件 Home
应该被渲染。但事实并非如此。我不知道如何调试这个。我已附上相关代码片段。
主要
ReactDOM.render(
<ErrorBoundary>
<Provider store={store}>
<Routes />
</Provider>
</ErrorBoundary>,
document.getElementById('root')
);
路线
export default function Routes() {
return (
<Router>
<Switch>
<Route exact path='/' component={App} />
<Route path='/login' component={Signin} />
<Route path='/register' component={Signup} />
</Switch>
</Router>
);
}
应用程序
export default function App() {
return <PrivateRoute component={Home} />
}
私人路线
export default function PrivateRoute({ component: Component, ...rest }) {
const authenticated = useAppSelector((state) => state.auth.isLogged);
return (
<Route
{...rest}
render={(props) =>
authenticated ? <Component {...props} /> : <Redirect to={'/login'} />
}
/>
);
}
登录
const Signin = () => {
const [state, handlers] = useSignin();
return (
<SigninUI {...state} {...handlers} />
)
}
export default Signin;
登录处理程序
const useSignin = (): [SigninState, SigninHandlers] => {
const dispatch = useAppDispatch();
const handleSubmit: SigninHandlers["handleSubmit"] = (e) => {
e.preventDefault();
apis.signin(state.email, state.pwd)
.then((data) => {
setState((prevState) => ({ ...prevState, errorMsg: "", successMsg: data.data.message }));
dispatch(authActions.login())
})
.catch((e) => {
setState((prevState) => ({ ...prevState, successMsg: "", errorMsg: e.data.message }));
})
}
return [state, { handleEmailChange, handlePwdChange, handleSubmit }]
}
useAppSelector、useAppDispatch
export const useAppDispatch = useDispatch.withTypes<AppDispatch>();
export const useAppSelector = useSelector.withTypes<RootState>();
商店
export const store = configureStore({
reducer: {
auth: authReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
authReducer
const initialState: AuthState = {
isLogged: false,
};
const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
login: (state) => {
state.isLogged = true;
},
logout: (state) => {
state.isLogged = false;
},
},
});
export const authActions = authSlice.actions;
export const authReducer = authSlice.reducer;
用户成功通过身份验证后,我没有看到任何从
"/login"
或 "/register"
导航用户的内容。您可以在身份验证后添加命令式重定向到 "/"
。
示例:
import { useHistory } from 'react-router-dom';
const useSignin = (): [SigninState, SigninHandlers] => {
const history = useHistory();
const dispatch = useAppDispatch();
const handleSubmit: SigninHandlers["handleSubmit"] = (e) => {
e.preventDefault();
apis.signin(state.email, state.pwd)
.then((data) => {
setState((prevState) => ({
...prevState,
errorMsg: "",
successMsg: data.data.message
}));
dispatch(authActions.login());
history.replace("/"); // <-- redirect to home page
})
.catch((e) => {
setState((prevState) => ({
...prevState,
successMsg: "",
errorMsg: e.data.message
}));
});
};
return [state, { handleEmailChange, handlePwdChange, handleSubmit }]
};
其他可能有帮助的事情是使用更正确的路由保护实现。
示例:
export default function PrivateRoute(props) {
const authenticated = useAppSelector((state) => state.auth.isLogged);
return authenticated ? <Route {...props} /> : <Redirect to="/login" />;
}
您可能还想创建一个受保护的路由,该路由与此组件相反,以保护经过身份验证的用户登录/注册路由。
export default function AnonymousRoute(props) {
const authenticated = useAppSelector((state) => state.auth.isLogged);
return authenticated ? <Redirect to="/" /> : <Route {...props} />;
}
用途:
export default function Routes() {
return (
<Router>
<Switch>
<PrivateRoute path='/login' component={Signin} />
<PrivateRoute path='/register' component={Signup} />
<AnonymousRoute path='/' component={Home} />
</Switch>
</Router>
);
}