【问题标题】:Assign local storage to react state. React Hooks分配本地存储以响应状态。反应钩子
【发布时间】:2020-06-26 12:41:44
【问题描述】:

我正在尝试让用户登录,并使用用户数据更新我的全局上下文。为了让用户保持登录状态,我将他们的数据存储在本地存储中。

我正在使用 react-hooks 来处理状态,因此我定义了一个状态:let [userData, setUserData] = useState({});

由于我不想让用户保持登录状态,因此我在登录期间将他们的数据存储在本地存储中。这很有效,并且数据实际上存储在本地存储中。

但是,我的问题是我无法将初始 userData 状态设置为等于本地存储中的当前数据。换句话说,userData 状态会在重新加载时重置为默认值。

我认为从本地存储中获取初始数据并将其分配给 useEffect 挂钩内的状态会起作用。但是在useEffect 内部调用setUserData 时状态不会更新。

AuthContext.js:

import React, { createContext, useState, useEffect } from 'react';

export const AuthContext = createContext();

const AuthContextProvider = props => {
    let [userData, setUserData] = useState({});

    const loginUser = (data) => {
        localStorage.setItem('userData', JSON.stringify({
            key: data.key,
            id: data.id,
            email: data.email,
            first_name: data.first_name,
            last_name: data.last_name
        })); // Save the user object in local storage
        setUserData({
            key: data.key,
            id: data.id,
            email: data.email,
            first_name: data.first_name,
            last_name: data.last_name
        }); // Set user data    
    };

    const logoutUser = () => {
        localStorage.removeItem('userData');
        setUserData({}); // Empty user data state
        newToast('Successfully signed out');
    };

    useEffect(() => {
        const localUser = JSON.parse(localStorage.getItem('userData'));
        if (localUser && localUser.key) {
            setUserData({
                key: localUser.key,
                id: localUser.id,
                email: localUser.email,
                first_name: localUser.first_name,
                last_name: localUser.last_name
            }); // Set user data    
        }
    }, [])


    return (
        <AuthContext.Provider value={{ userData, loginUser, logoutUser, newToast }}>
            {props.children}
        </AuthContext.Provider>
    )
}

export default AuthContextProvider;

Signin.js:

const Signin = props => {
    let [loading, setLoading] = useState(false);
    let [formError, setFormError] = useState(false);
    const { userData, loginUser, newToast } = useContext(AuthContext);
    const { register, handleSubmit, errors, setError, clearError } = useForm();

    const onSubmit = e => {
        setLoading(true);
        setFormError(false);
        clearError(); // Clear all erros on form        
        axios
            .post('users/auth/login/', {
                headers: { 'Content-Type': 'application/json' },
                email: `${e.email}`,
                password: `${e.password}`,
            })
            .then(res => {
                const { data } = res
                loginUser(data);
                newToast('Successfully signed in');
            })
            .catch((error) => {
                const { data } = error.response;
                console.log(data);
                data.email && setError("email", "", data.email);
                data.password1 && setError("password", "", data.password1);
                setFormError(true);
            })

        setLoading(false);
    };
    return ( ... );
}

【问题讨论】:

    标签: reactjs authentication local-storage token react-hooks


    【解决方案1】:

    这样使用useReducer怎么样?

    const [user, setUser] = useReducer((prev, cur) => {
      localStorage.setItem('userData', JSON.stringify(cur));
      return cur;
    }, JSON.parse(localStorage.getItem('userData')));
    

    你可以打电话

    setUser({ key: '1', ... });
    

    【讨论】:

      【解决方案2】:

      如果我理解您的问题,您可以执行以下操作:

      const [user, setUser] = useState([], () => {
              const localData = localStorage.getItem('userData');
              return localData ? JSON.parse(localData) : [];
          });
      

      【讨论】:

        【解决方案3】:

        所以我想出了一个解决方案!

        在 AuthContext.js 中,我不需要在 useEffect 中分配状态。 相反,我在定义状态挂钩时直接获取初始数据:

        const localUser = JSON.parse(localStorage.getItem('userData')) || {};
        let [userData, setUserData] = useState(localUser);
        

        这样我就根本不需要useEffect 钩子了。

        我希望这是推荐的做法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-02
          • 2021-10-12
          • 2020-10-23
          • 1970-01-01
          • 2019-02-20
          • 2020-03-10
          相关资源
          最近更新 更多