使用 react-router-dom (v6) 成功登录后,Reactjs 重定向到仪表板页面
Reactjs redirect to dashboard page after successful login with react-router-dom (v6)
我正在使用 redux/toolkit 处理简单的 reactjs 登录表单。我想在成功登录后重定向到 dashboard
页面。它抛出以下错误。我是 reactjs 的新手,如果我遗漏了什么请告诉我。
错误:
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;
当你使用 react hooks 时,有一些规则你不能绕过它们
- 您必须在组件的根级别调用 useHook() 或
函数
- 您不能进行有条件的 useHook() 调用
我想,但也许我错了,你的这部分代码出现了错误
export const submitLogin =
({
email,
password
}) =>
async dispatch => {
const history = useNavigate(); // x Wrong you can't call inside another function
...
};
问题
您正试图在 React 组件之外使用 useNavigate
挂钩,这是一种无效的使用。 React hooks 必须在 top-level 处调用,它们不能有条件地在函数、循环等中调用...
解决方案
将导航功能传递给 submitLogin
动作创建者。
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
返回的 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>
);
}
我正在使用 redux/toolkit 处理简单的 reactjs 登录表单。我想在成功登录后重定向到 dashboard
页面。它抛出以下错误。我是 reactjs 的新手,如果我遗漏了什么请告诉我。
错误:
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;
当你使用 react hooks 时,有一些规则你不能绕过它们
- 您必须在组件的根级别调用 useHook() 或
函数 - 您不能进行有条件的 useHook() 调用
我想,但也许我错了,你的这部分代码出现了错误
export const submitLogin =
({
email,
password
}) =>
async dispatch => {
const history = useNavigate(); // x Wrong you can't call inside another function
...
};
问题
您正试图在 React 组件之外使用 useNavigate
挂钩,这是一种无效的使用。 React hooks 必须在 top-level 处调用,它们不能有条件地在函数、循环等中调用...
解决方案
将导航功能传递给 submitLogin
动作创建者。
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
返回的 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>
);
}