【问题标题】:How to convert localStorage code in React to AsyncStorage in React Native?如何将 React 中的 localStorage 代码转换为 React Native 中的 AsyncStorage?
【发布时间】:2020-06-22 16:11:40
【问题描述】:

我想知道如何使用 AsyncStorage 将我的 React 代码转换为 React Native。我已经尝试了下面的代码,但我得到了“isAuthenticated”的“未定义”以及“JSON.parse(AsyncStorage.getItem('token')”中的“错误”。我想使用“isAuthenticated”值来显示只有组件的特定部分。

反应代码:

export const Auth = (state = {
        isLoading: false,
        isAuthenticated: localStorage.getItem('token') ? true : false,
        token: localStorage.getItem('token'),
        user: localStorage.getItem('creds') ? JSON.parse(localStorage.getItem('creds')) : null,
        errMess: null
    }, action) => {
    switch (action.type) {
        case ActionTypes.LOGIN_REQUEST:
            return {...state,
                isLoading: true,
                isAuthenticated: false,
                user: action.creds
            };
        case ActionTypes.LOGIN_SUCCESS:
            return {...state,
                isLoading: false,
                isAuthenticated: true,
                errMess: '',
                token: action.token
            };
        case ActionTypes.LOGIN_FAILURE:
            return {...state,
                isLoading: false,
                isAuthenticated: false,
                errMess: action.message
            };
        case ActionTypes.LOGOUT_REQUEST:
            return {...state,
                isLoading: true,
                isAuthenticated: true
            };
        case ActionTypes.LOGOUT_SUCCESS:
            return {...state,
                isLoading: false,
                isAuthenticated: false,
                token: '',
                user: null
            };
        default:
            return state
    }
}

我在 React Native 中的代码:

import * as ActionTypes from './ActionTypes';

// The auth reducer. The starting state sets authentication
// based on a token being in local storage. In a real app,
// we would also want a util to check if the token is expired.
export const auth = (state = {
  isLoading: false,
  isAuthenticated: false,
  token: null,
  user: null,
  errMess: null
}, action) => {
  switch (action.type) {
    case ActionTypes.GET_AUTH:
      return {
        ...state,
        ...action.payload
      };
    case ActionTypes.LOGIN_REQUEST:
      return {
        ...state,
        isLoading: true,
        isAuthenticated: false,
        user: action.creds
      };
    case ActionTypes.LOGIN_SUCCESS:
      return {
        ...state,
        isLoading: false,
        isAuthenticated: true,
        errMess: '',
        token: action.token
      };
    case ActionTypes.LOGIN_FAILURE:
      return {
        ...state,
        isLoading: false,
        isAuthenticated: false,
        errMess: action.message
      };
    case ActionTypes.LOGOUT_REQUEST:
      return {
        ...state,
        isLoading: true,
        isAuthenticated: true
      };
    case ActionTypes.LOGOUT_SUCCESS:
      return {
        ...state,
        isLoading: false,
        isAuthenticated: false,
        token: '',
        user: null
      };
    default:
      return state
  }
}

提前致谢。

编辑:这是我更新的代码。

export const getAuth = () => {
  return async(dispatch) => {
    const [token, creds] = await Promise.all([
      AsyncStorage.getItem('token'),
      AsyncStorage.getItem('creds')
    ])

    dispatch({
      type: ActionTypes.GET_AUTH,
      payload: {
        isLoading: false,
        isAuthenticated: !!token,
        token: token,
        user: JSON.parse(creds),
        errMess: null
      }
    });
  }
}

export const loginUser = (creds) => (dispatch) => {
  // We dispatch requestLogin to kickoff the call to the API
  dispatch(requestLogin(creds))

  return fetch(baseUrl + 'users/login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(creds)
    })
    .then(response => {
        if (response.ok) {
          return response;
        } else {
          var error = new Error('Error ' + response.status + ': ' + response.statusText);
          error.response = response;
          throw error;
        }
      },
      error => {
        throw error;
      })
    .then(response => response.json())
    .then(response => {
      if (response.success) {
        async() => {
          try {
            await AsyncStorage.setItem('token', response.token);
            await AsyncStorage.setItem('creds', JSON.stringify(creds));
          } catch (error) {
            // Error saving data
          }
        }
        // If login was successful, set the token in local storage
        //AsyncStorage.setItem('token', response.token);
        //AsyncStorage.setItem('creds', JSON.stringify(creds));
        // Dispatch the success action
        dispatch(fetchSaves());
        dispatch(receiveLogin(response));
      } else {
        var error = new Error('Error ' + response.status);
        error.response = response;
        throw error;
      }
    })
    .catch(error => dispatch(loginError(error.message)))
};

【问题讨论】:

    标签: reactjs react-native asyncstorage jsonparser


    【解决方案1】:

    我认为您应该将 initialState 保留为默认值,使用 redux-thunk 并在应用启动时调度一个操作以获取身份验证数据。

    const getAuth = () => {
        return async (dispatch) => {
            const [token, user] = await Promise.all([
              AsyncStorage.getItem('token'),
              AsyncStorage.getItem('creds')
            ])
    
            dispatch({
              type: 'GET_AUTH',
              payload: {
                isLoading: false,
                isAuthenticated: !!token,
                token,
                user: JSON.parse(creds),
                errMess: null
              }
            });
        }
    }
    
    const App = connect({}, {getAuth})(({getAuth}) => {
    
      useEffect(() => {
        getAuth();
      }, [])
      
      return ...
    })
    
    export const auth = async (state = {
        isLoading: false,
        isAuthenticated: false,
        token: null,
        user: null,
        errMess: null
    }, action) => {
        switch (action.type) {
            case ActionTypes.GET_AUTH:
                return {
                    ...state,
                    ...action.payload
                };
            ...
    }
    

    【讨论】:

    • 成功了!!但是我必须对身份验证文件进行更改——我必须在 ActionTypes.GET_AUTH 中删除 ...action.payload,只留下 ...state。我不明白为什么,但更改后它可以工作
    • 在返回状态之前你能console.log(action.payload)吗?
    • 完美运行。即使有......有效载荷。非常感谢!!
    【解决方案2】:

    AsyncStorage 是异步的。 使用

    const value = await AsyncStorage.getItem('token');
    

    【讨论】:

    • 我尝试了上述解决方案,但出现错误提示“无法在异步函数之外使用关键字 'await'”
    • 所以让你的函数异步
    【解决方案3】:

    @Samir Kumar试试这个

    import { AsyncStorage } from 'react-native';
    
    async functionName(){
      const token = await AsyncStorage.getItem('token');
    }
    

    【讨论】:

    • 以上方法我都试过了。将令牌保存在 AsyncStorage 中似乎存在问题,因此它返回空值。请检查我的 loginUser 函数。
    猜你喜欢
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 2019-11-03
    • 1970-01-01
    • 2019-01-03
    相关资源
    最近更新 更多