Redux 状态更改不会根据逻辑重新渲染组件

问题描述 投票:0回答:1

我有一个带有 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;
javascript reactjs redux react-router-dom redux-toolkit
1个回答
0
投票

用户成功通过身份验证后,我没有看到任何从

"/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>
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.