【问题标题】:React Native Auth Flow with Redux (New Version) Token Fetch ProblemReact Native Auth Flow with Redux(新版本)令牌获取问题
【发布时间】:2021-12-09 14:51:00
【问题描述】:

所以我有一个响应原生的移动应用程序,我正在尝试为其正确创建身份验证流。我首先将其作为网络应用程序,然后现在尝试与移动应用程序相同。我正在使用 redux 进行状态管理。

流程如下:一旦用户登录或注册,我使用 axios 将数据发送到后端。后端生成用户令牌。我想创建一个系统,我可以在用户登录时获取令牌并将其存储在 AsyncStorage 中,以便在用户尝试再次打开应用程序时直接登录。

这是代码,非常乐意回答任何问题,这是通过 react 教程完成的:

LoginScreen.js

const Login = ( { navigation }) => {

  const [email, setEmail] = useState();
  const [password, setPassword] = useState();
  const [message, setMessage] = useState(null)

  // Errors
  const [EmailMessage, setEmailMessage] = useState(null);
  const [PasswordMessage, setPasswordMessage] = useState(null);

  const dispatch = useDispatch();

  const userLogin = useSelector((state) => state.userLogin);
  const { loading, error, userInfo } = userLogin

  useEffect(() => {

      if (userInfo) {
          navigation.navigate('MainTabs', { screen: 'Home'});
      }
  }, [navigation, userInfo]);

  const submitHandler = (e) => {  
    
    e.preventDefault();
    
    if (!email) {
      alert('Please fill in the email');
      return
    };
    if (!password) {
      alert('Please fill in the password');
      return
    }
       
    dispatch(login(email, password));

    };

返回部分是前端代码,为简洁起见,省略了

现在是 redux 部分:

userActions.js

import axios from "axios";
import { USER_LOGIN_FAIL, USER_LOGIN_REQUEST, USER_LOGIN_SUCCESS, USER_LOGOUT, USER_REGISTER_FAIL, USER_REGISTER_SUCCESS, USER_REGISTER_REQUEST } from "../constants/userConstants"
import AsyncStorage from '@react-native-async-storage/async-storage';



export const login = (email, password) => async(dispatch) => {
    try {
        dispatch({ type: USER_LOGIN_REQUEST });

        const config = {
            headers: {
                "Content-type": "application/json"
            }
        }

        const {data} = await axios.post("api/url", {email, password}, config)
        dispatch({type: USER_LOGIN_SUCCESS, payload:data});
        
        await AsyncStorage.setItem("userInfo", JSON.stringify(data))
        
    } catch (error) {
        dispatch({
            type: USER_LOGIN_FAIL,
            payload: 
                error.response && error.response.data.message
                    ? error.response.data.message 
                    : error.message,
        })

        console.log("This login attempt is unsuccessful");
        
    }
}

export const logout = () => async (dispatch) => {
    await AsyncStorage.removeItem("userInfo")
    dispatch({ type: USER_LOGOUT });
};

export const register = (full_name, email, password, social) => async(dispatch) => {
    try {

        dispatch({type: USER_REGISTER_REQUEST});

        const config = {
            headers: {
                "Content-type": "application/json"
            }
        };

        const {data} = await axios.post("api/url", {full_name, email, password, social}, config);

        dispatch({ type: USER_REGISTER_SUCCESS, payload: data});
        dispatch({ type: USER_LOGIN_SUCCESS, payload: data});

        await AsyncStorage.setItem("userInfo", JSON.stringify(data))

    } catch (error) {
        dispatch({type: USER_REGISTER_FAIL, payload:
            error.response && error.response.data.message
                ? error.response.data.message
                : error.message      
    })
}}

userReducers.js

import { USER_LOGIN_REQUEST, USER_REGISTER_FAIL, USER_REGISTER_REQUEST, USER_REGISTER_SUCCESS } from "../constants/userConstants";
import { USER_LOGIN_SUCCESS, USER_LOGIN_FAIL, USER_LOGOUT   } from "../constants/userConstants";

export const userLoginReducer = (state = {}, action) => {
    switch (action.type) {
        case USER_LOGIN_REQUEST:
            return {loading: true}
        case USER_LOGIN_SUCCESS:
            return {loading: false, userInfo: action.payload}
        case USER_LOGIN_FAIL:
            return {loading: false, error:action.payload}
        case USER_LOGOUT:
            return {}

   
        default:
            return state;
    }
}

export const userRegisterReducer = (state = {}, action) => {
    switch (action.type) {
        case USER_REGISTER_REQUEST:
            return {loading:true}    
        case USER_REGISTER_SUCCESS:
            return {loading:false, userInfo: action.payload}
        case USER_REGISTER_FAIL:
            return {loading:false, error: action.payload}
            
        default:
            return state;
    }
}

store.js

import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from "redux-thunk";
import { userLoginReducer, userRegisterReducer } from './src/redux/reducers/userReducers';
import AsyncStorage from '@react-native-async-storage/async-storage';

const reducer = combineReducers({
    //contains reducers
    userLogin: userLoginReducer,
    userRegister: userRegisterReducer
});

const middleware = [thunk];


const getData = async () => {
    try {
        const value = await AsyncStorage.getItem("userInfo")
        return value != null ? JSON.parse(value) : null;
        
    } catch(e) {
        console.log("this attempt is not successful");
    }
}

const userInfoFromStorage = getData() || null;
alert(JSON.stringify(userInfoFromStorage))

const initialState = {
    userLogin: {userInfo: userInfoFromStorage}
};


const store = createStore(
    reducer,
    initialState,
    applyMiddleware(...middleware)
);

export default store

我将不胜感激这里的任何帮助,因为我无法解决如何解决这个问题,这是一个关于 fetch 的承诺问题或更普遍的问题。注册用户后,我会在后端生成一个令牌。如果有人知道如何获取和保存该令牌并在用户已经登录的情况下让用户登录的最佳方法,我将不胜感激

【问题讨论】:

  • 我很高兴您发现我的回答很有帮助 :) 如果此答案或任何答案解决了您的问题,请考虑通过单击复选标记或投票来接受它(一旦您有足够的声誉可以做所以)。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。谢谢

标签: reactjs react-native react-redux asyncstorage


【解决方案1】:

首先,创建一个名为 authProvider.ts 的文件。这将保存对象,键为isAuthenticatedasync getAuthToken(),回调函数为属性。

const authProvider: any = {
  isAuthenticated: false,
  authToken: null,
  async getAuthToken(callback: VoidFunction) {
    await GetSessionData('Access-token').then(
      res => {
        if (res) {
          authProvider.isAuthenticated = true;
          authProvider.authToken = res;
          callback();
        } else {
          authProvider.isAuthenticated = false;
          authProvider.authToken = res;
          callback();
        }
      }
    ); 
  }
};

export { authProvider };

export const GetSessionData =  async (key: string) => {
  return await AsyncStorage.getItem(
    key,
    (err, value) => {
      if (err) {
          console.log(err);
      } else {
        return value;
      }
    }
  );
}

在 app.tsx 中 在 App 组件中,我们将调用上述 authProvider 以使用 awaitAsync storage 获取令牌。一旦完成,它将执行下面的回调函数逻辑。

const App = () => {
const [isLoading, setLoading] = useState<boolean>(true);
useEffect(() => {
 authProvider.getAuthToken(() => {
  if (authProvider.isAuthenticated) {
   store.dispatch(isAuthenticatedUser(true));
   setLoading(false);
  } else {
    store.dispatch(isAuthenticatedUser(false));
    setLoading(false);
    // *** redirect to login page logic ***.
  }
 });
}, []);
return (
  <>
     <Provider store={store}>
       {
         !isLoading ?
         <Dashboard /> :
         <AppLoader />
       }
     </Provider>
   </>
 );
}

【讨论】:

    猜你喜欢
    • 2019-02-28
    • 2022-10-13
    • 1970-01-01
    • 2018-01-20
    • 2017-04-06
    • 1970-01-01
    • 2017-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多