简体   繁体   English

如何使用 Django 后端保持用户登录 React 应用程序

[英]How to keep user logged in in React app with a Django back-end

I have a very famous problem which I think everybody has at least once tackled.我有一个非常著名的问题,我认为每个人都至少解决过一次。 I want to persist the user logged-in in my react app even if the page is refreshed.即使页面被刷新,我也想在我的反应应用程序中保持用户登录。 I have read all the related questions and articles about how this can be done but unfortunately I got nowhere.我已经阅读了有关如何做到这一点的所有相关问题和文章,但不幸的是我一无所获。 In my ProtectedComponent I have the following code:在我的 ProtectedComponent 我有以下代码:

const ProtectedRoute = ({ notLoggedInPath }) => {
  
  const isLoggedIn = useSelector((state) => state.auth.isLoggedIn);

  return (
    <Fragment>
      {isLoggedIn && <RecorderPage />}
      {!isLoggedIn && <Redirect to={notLoggedInPath} />}
    </Fragment>
  );
};

As you can see I have implemented a variable so-called isLoggedIn in my initialState of auth reducer and if this variable is true the protected route will be accessible otherwise not.如您所见,我在我的 auth reducer 的 initialState 中实现了一个名为 isLoggedIn 的变量,如果此变量为真,则受保护的路由将可访问,否则不可访问。

In my Sign In component I store the received token from the api to the localStorage.在我的登录组件中,我将从 api 接收到的令牌存储到 localStorage。 This is completely done.这完全完成了。 But my main question is that when the user signs in and then navigates to a protected route, by refreshing the page my initialState(isLoggedIn) goes away and changes to false, making the user logged out.但我的主要问题是,当用户登录然后导航到受保护的路线时,通过刷新页面,我的 initialState(isLoggedIn) 消失并更改为 false,从而使用户注销。 This is completely natural in the culture of ReactJS.这在 ReactJS 的培养中是完全自然的。 But how can I implement a way in which when my app is being launched, it looks for authenticating the previously received token and if it has not expired yet it navigates the user to the page on which the app is refreshed.但是我如何实现一种方式,在启动我的应用程序时,它会查找对先前接收到的令牌进行身份验证,如果它尚未过期,它会将用户导航到刷新应用程序的页面。 This is done by a gigantic number of websites so I know it can be done.这是由大量网站完成的,所以我知道可以做到。 But I don't know how?但我不知道怎么做?

My sign in component:我的登录组件:

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/>
)

It is worth mentioning that I have also used the hook useEffect in my mother-level component App.值得一提的是,我的母级组件App中也使用了钩子useEffect。 I mean when my app launches the callback in useEffect checks if the localStorage token can be authorised or not but because of async nature of js and also axios request this is not a solution since the initialState is set before the response of this axios request is received.我的意思是当我的应用程序在 useEffect 中启动回调时检查是否可以授权 localStorage 令牌,但由于 js 的异步性质以及 axios 请求,这不是解决方案,因为在收到此 axios 请求的响应之前设置了 initialState .

My App component:我的应用组件:

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>
)

When the page reloads execute the async logic in useEffect hook on App.js.当页面重新加载时,在 App.js 上的 useEffect 挂钩中执行异步逻辑。 Use a state like authChecking to show a loader while the auth state is being checked.在检查 auth state 时,使用 state 之类的authChecking来显示加载程序。

const [authChecking, updateAuthChecking] = useState(true)

useEffect(() => {
  asyncFunc
  .then(updateUserObjToStore)
  .finally(() => updateAuthChecking(false))
}, [])

I have also written a article on medium about this feel free to check it out if you have any doubts.我还在媒体上写了一篇关于此的文章,如果您有任何疑问,请随时查看。 https://medium.com/@jmathew1706/configuring-protected-routes-in-react-using-react-router-af3958bfeffd https://medium.com/@jmathew1706/configuring-protected-routes-in-react-using-react-router-af3958bfeffd

Bonus tip: Try to keep this logic in a custom hook will ensure proper separation of concerns.额外提示:尝试将此逻辑保留在自定义挂钩中将确保正确分离关注点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从 Django(后端)向 React Native(移动)应用程序发送通知 - How to send Notification to React Native (mobile) app from Django (back-end) 如何使用本地后端在本地运行生产反应应用程序 - How to run production react app in local with local back-end 如何在具有 Django 后端的 React Native 应用程序上保持用户登录(即使手机关闭)? - How to keep a user logged in (even when phone turns off ) on a React Native app with Django backend? 如何使用自定义后端API将&#39;create-react-app&#39;部署到Heroku - How to deploy 'create-react-app' to Heroku with custom back-end api React 应用程序(或任何 SPA)应该如何与 HATEOAS 后端交互? - How should a React app (or any SPA) interact with a HATEOAS back-end? 如何使用Express和React作为UI构建器在后端处理路由 - How to handle routes in back-end with Express and React as UI builder 我如何在反应中显示后端响应? - How can i Show Back-End response in react? 如何让 React 组件从后端接收更新? - How to make a react component receive updates from the back-end? 将列表从前端 (react) 传递到后端 (django) - Passing a list form the front-end (react) to the back-end (django) 使用 react 前端和 express 后端在用户注册后触发自动登录 - Trigger automatic login after user registration using react front end with express back-end
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM