我正在使用redux/toolkit处理简单的reactjs登录表单.我想在成功登录后重定向到dashboard页.它抛出了以下错误.我是reactjs的新手,如果我错过了什么,请告诉我.

Error:

Uncaught (in promise) Error: Invalid hook call. Hooks can only be called inside of the body of a function component.

authSlice.js

import { useNavigate } from 'react-router-dom';


export const submitLogin =
  ({
    email,
    password
  }) =>
  async dispatch => {
    const history = useNavigate();

    return jwtService
      .signInWithEmailAndPassword(email, password)
      .then(user => {
        history('/dashboard');
        return dispatch(loginSuccess());
      })
      .catch(error => {
        return dispatch(loginError(error));
      });
  };


const authSlice = createSlice({
    name: 'auth',
    initialState,
    reducers: {
        loginSuccess: ....
        loginError: ....
        logoutSuccess: ....
    },
    extraReducers: {},
});

export const { loginSuccess, loginError, logoutSuccess } = authSlice.actions;

export default authSlice.reducer;

Login.js

const Login = () => {
   function handleSubmit(model) {
     dispatch(submitLogin(model));
   }

   return (
       <Formsy onValidSubmit={handleSubmit} ref={formRef}>
           <input type="text" placeholder="username" />
           ....
       </Formsy>
    )
}

App.js

<Routes>
  <Route path="/dashboard" element={<ProtectedRoutes />}>
  <Route path="" element={<Dashboard />} />
  </Route>
  <Route exact path="/" element={<Login />} />
  <Route path="*" element={<PageNotFound />} />
</Routes>
import React from 'react';
import { useSelector } from 'react-redux';
import { Navigate, Outlet } from 'react-router-dom';

const useAuth = () => {
    const auth = useSelector(({ auth }) => auth);
    return auth && auth.loggedIn;
};

const ProtectedRoutes = () => {
    const isAuth = useAuth();
    return isAuth ? <Outlet /> : <Navigate to="/" />
}

export default ProtectedRoutes;

推荐答案

Issue

您试图在React组件外部使用useNavigate钩子,这是无效的.React钩子必须在顶层调用,不能在函数、循环等中有条件地调用它们...

Rules of hooks

Solutions

Pass the navigate function to the submitLogin action creator.

export const submitLogin = ({ email, password }, navigate) =>
  async dispatch => {
    return jwtService
      .signInWithEmailAndPassword(email, password)
      .then(user => {
        navigate('/dashboard');
        return dispatch(loginSuccess());
      })
      .catch(error => {
        return dispatch(loginError(error));
      });
  };

...

const Login = () => {
  const navigate = useNavigate();

  function handleSubmit(model) {
    dispatch(submitLogin(model, navigate));
  }

  return (
    <Formsy onValidSubmit={handleSubmit} ref={formRef}>
      <input type="text" placeholder="username" />
      ....
    </Formsy>
  );
}

Chain/await the returned Promise

export const submitLogin = ({ email, password }) =>
  async dispatch => {
    return jwtService
      .signInWithEmailAndPassword(email, password)
      .then(user => {
        dispatch(loginSuccess());
        return user;
      })
      .catch(error => {
        dispatch(loginError(error));
        throw error;
      });
  };

...

const Login = () => {
  const navigate = useNavigate();

  async function handleSubmit(model) {
    try {
      await dispatch(submitLogin(model));
      navigate('/dashboard');
    } catch(error) {
      // handle error, log, etc...
    }
  }

  return (
    <Formsy onValidSubmit={handleSubmit} ref={formRef}>
      <input type="text" placeholder="username" />
      ....
    </Formsy>
  );
}

Reactjs相关问答推荐

404使用GitHub操作部署Next.js应用程序时出错

在Reaction中测试条件组件

使用useReducer时,props 未从父级传递给子或孙级

react 路由GUGUD Use Effect无法通过useNavigate正常工作

React中的useEffect钩子

使用`Link`包装`tr`标记会在Next.js中产生水合错误14

Reaction上下文值无法传递给其他组件

试图从Amazon-Cogito-Identity-js模拟CogitoUser.authateUser,并将其获取为未定义的S

在迭代状态时无法读取未定义的属性(读取 map )

我从 S3 存储桶下载图像时收到错误

在Vite React上获取Amplify的环境变量

React v6 中的公共和私有路由

next js 13 在获取中使用标头时动态渲染而不是静态渲染?

在 React 中将路径与查询变量匹配

我刚刚部署了我的 Vite React 站点,但我的图标/图像没有部署

在 Formik 表单中访问子组件的值

Mui CardMedia 的图片组件

CORS 政策:无访问控制允许来源-AWS 和 Vercel

为什么我从另一个组件收到错误?

为什么这两个 div 的渲染方式不同?