如何使用 Django 后端让用户登录 React 应用程序
How to keep user logged in in React app with a Django back-end
我有一个非常著名的问题,我认为每个人都至少解决过一次。即使页面已刷新,我也希望用户在我的 React 应用程序中保持登录状态。我已经阅读了所有关于如何做到这一点的相关问题和文章,但不幸的是我一无所获。
在我的 ProtectedComponent 中,我有以下代码:
const ProtectedRoute = ({ notLoggedInPath }) => {
const isLoggedIn = useSelector((state) => state.auth.isLoggedIn);
return (
<Fragment>
{isLoggedIn && <RecorderPage />}
{!isLoggedIn && <Redirect to={notLoggedInPath} />}
</Fragment>
);
};
如您所见,我在 auth reducer 的 initialState 中实现了一个名为 isLoggedIn 的变量,如果此变量为真,则受保护的路由将可访问,否则不可访问。
在我的登录组件中,我将从 api 接收到的令牌存储到 localStorage。这完全完成了。但我的主要问题是,当用户登录然后导航到受保护的路由时,通过刷新页面,我的 initialState(isLoggedIn) 消失并更改为 false,使用户注销。这在 ReactJS 的文化中是完全自然的。但是我如何实现一种方式,在我的应用程序启动时,它会寻找对先前收到的令牌进行身份验证,如果它尚未过期,它会将用户导航到刷新应用程序的页面。这是由大量网站完成的,所以我知道这是可以做到的。但是我不知道怎么办?
我的登录组件:
const SignInForm = () => {
const dispatch = useDispatch();
const history = useHistory();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = () => {
axios({
method: 'post',
url: 'someurl/api/token/',
data: {
username: username,
password: password,
},
})
.then((res) => {
const token = res.data.access;
localStorage.setItem('token', token);
dispatch(updateUserInStore(token, username));
dispatch(makeUserLoggedIn());
history.push('/recorder');
})
.catch((err) => {
console.log(err);
console.log(err.response);
});
};
return (
<some jsx/>
)
值得一提的是,我在自己的母级组件App中也使用过useEffect hook。我的意思是,当我的应用程序在 useEffect 中启动回调时,会检查是否可以授权 localStorage 令牌,但是由于 js 的异步性质以及 axios 请求,这不是解决方案,因为在收到此 axios 请求的响应之前设置了 initialState .
我的应用组件:
const App = () => {
const dispatch = useDispatch();
const history = useHistory();
const tokenLocalStored = localStorage.getItem('token');
const checkIfUserCanBeLoggedIn = () => {
const token = localStorage.getItem('token');
axios({
method: 'get',
url: 'some-url/api/sentence',
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
dispatch(makeUserLoggedIn());
})
.catch((err) => {
console.log(err);
console.log(err.response);
return false;
});
};
useEffect(() => {
checkIfUserCanBeLoggedIn();
});
return (
<Some JSX>
)
当页面重新加载时,在 App.js 上执行 useEffect 钩子中的异步逻辑。使用 authChecking 之类的状态在检查身份验证状态时显示加载程序。
const [authChecking, updateAuthChecking] = useState(true)
useEffect(() => {
asyncFunc
.then(updateUserObjToStore)
.finally(() => updateAuthChecking(false))
}, [])
我在medium上也写过一篇关于这个的文章,有疑问的可以看看。
https://medium.com/@jmathew1706/configuring-protected-routes-in-react-using-react-router-af3958bfeffd
额外提示:尝试将此逻辑保留在自定义挂钩中将确保正确分离关注点。
我有一个非常著名的问题,我认为每个人都至少解决过一次。即使页面已刷新,我也希望用户在我的 React 应用程序中保持登录状态。我已经阅读了所有关于如何做到这一点的相关问题和文章,但不幸的是我一无所获。 在我的 ProtectedComponent 中,我有以下代码:
const ProtectedRoute = ({ notLoggedInPath }) => {
const isLoggedIn = useSelector((state) => state.auth.isLoggedIn);
return (
<Fragment>
{isLoggedIn && <RecorderPage />}
{!isLoggedIn && <Redirect to={notLoggedInPath} />}
</Fragment>
);
};
如您所见,我在 auth reducer 的 initialState 中实现了一个名为 isLoggedIn 的变量,如果此变量为真,则受保护的路由将可访问,否则不可访问。
在我的登录组件中,我将从 api 接收到的令牌存储到 localStorage。这完全完成了。但我的主要问题是,当用户登录然后导航到受保护的路由时,通过刷新页面,我的 initialState(isLoggedIn) 消失并更改为 false,使用户注销。这在 ReactJS 的文化中是完全自然的。但是我如何实现一种方式,在我的应用程序启动时,它会寻找对先前收到的令牌进行身份验证,如果它尚未过期,它会将用户导航到刷新应用程序的页面。这是由大量网站完成的,所以我知道这是可以做到的。但是我不知道怎么办?
我的登录组件:
const SignInForm = () => {
const dispatch = useDispatch();
const history = useHistory();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = () => {
axios({
method: 'post',
url: 'someurl/api/token/',
data: {
username: username,
password: password,
},
})
.then((res) => {
const token = res.data.access;
localStorage.setItem('token', token);
dispatch(updateUserInStore(token, username));
dispatch(makeUserLoggedIn());
history.push('/recorder');
})
.catch((err) => {
console.log(err);
console.log(err.response);
});
};
return (
<some jsx/>
)
值得一提的是,我在自己的母级组件App中也使用过useEffect hook。我的意思是,当我的应用程序在 useEffect 中启动回调时,会检查是否可以授权 localStorage 令牌,但是由于 js 的异步性质以及 axios 请求,这不是解决方案,因为在收到此 axios 请求的响应之前设置了 initialState .
我的应用组件:
const App = () => {
const dispatch = useDispatch();
const history = useHistory();
const tokenLocalStored = localStorage.getItem('token');
const checkIfUserCanBeLoggedIn = () => {
const token = localStorage.getItem('token');
axios({
method: 'get',
url: 'some-url/api/sentence',
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
dispatch(makeUserLoggedIn());
})
.catch((err) => {
console.log(err);
console.log(err.response);
return false;
});
};
useEffect(() => {
checkIfUserCanBeLoggedIn();
});
return (
<Some JSX>
)
当页面重新加载时,在 App.js 上执行 useEffect 钩子中的异步逻辑。使用 authChecking 之类的状态在检查身份验证状态时显示加载程序。
const [authChecking, updateAuthChecking] = useState(true)
useEffect(() => {
asyncFunc
.then(updateUserObjToStore)
.finally(() => updateAuthChecking(false))
}, [])
我在medium上也写过一篇关于这个的文章,有疑问的可以看看。 https://medium.com/@jmathew1706/configuring-protected-routes-in-react-using-react-router-af3958bfeffd
额外提示:尝试将此逻辑保留在自定义挂钩中将确保正确分离关注点。