javascript-如何对redux使用react native asyncstorage?

我已经进行了登录和注销操作以及userReducer.如何将异步存储与redux集成?我正在使用redux thunk作为中间件.

我能够使用内部状态变量来实现登录和注销,但是我无法理解如何将其分解为动作和reducer,以及如何使用asyncstorage来存储accessToken.

原始代码:

_onLogin = () => {
    auth0.webAuth
      .authorize({
        scope: 'openid profile',
        audience: 'https://' + credentials.domain + '/userinfo'
      })
      .then(credentials => {
        this.setState({ accessToken: credentials.accessToken });
      })
      .catch(error => console.log(error));
  };

  _onLogout = () => {
    if (Platform.OS === 'android') {
      this.setState({ accessToken: null });
    } else {
      auth0.webAuth
        .clearSession({})
        .then(success => {
          this.setState({ accessToken: null });
        })
        .catch(error => console.log(error));
    }
  };

loginAction.js:

   import { LOGIN_USER } from './types';
import Auth0 from 'react-native-auth0';

var credentials = require('./auth0-credentials');
const auth0 = new Auth0(credentials);

export const loginUser = () => dispatch => {
    auth0.webAuth
    .authorize({
      scope: 'openid profile',
      audience: 'https://' + credentials.domain + '/userinfo'
    })
    .then(credentials =>
        dispatch({
            type: LOGIN_USER,
            payload: credentials.accessToken
        })
    )
    .catch(error => console.log(error));
}

logoutAction.js:

       import { LOGOUT_USER } from './types';
import Auth0 from 'react-native-auth0';

var credentials = require('./auth0-credentials');
const auth0 = new Auth0(credentials);

export const logoutUser = () => dispatch => {

        auth0.webAuth
          .clearSession({})
          .then(success => 
                dispatch({
                    type: LOGOUT_USER,
                    payload: null
                })
          )
          .catch(error => console.log(error));
}

userReducer.js:

  import { LOGIN_USER, LOGOUT_USER } from '../actions/types';

const initialState = {
    accessToken: null
}

export default function (state = initialState, action) {
    switch (action.type) {

        case LOGIN_USER:

            _storeData = async () => {
                try {
                    await AsyncStorage.setItem('accessToken', action.payload);
                } catch (error) {
                    console.log(error)
                }
            }

            return {
               ...state,
               accessToken:action.payload
            };

        case LOGOUT_USER:

            _removeData = async (accessToken) => {
                try {
                    await AsyncStorage.removeItem(accessToken);
                } catch (error) {
                    console.log(error)
                }
            }    

            return {
                ...state,
                accessToken:action.payload
            };

        default:
            return state;
    }
}

我是Redux的新手,所以我尝试将原始代码转换为动作和reducer,但是不确定我是否在userReducer.js中正确实现了asyncstorage?

解决方法:

您可以方便地单独使用AsyncStorage或redux来管理身份验证状态.取决于您是否适应.我会给你一个例子.

对于AsyncStorage:
假设您具有仅在2周内有效的身份验证密钥.您可以在用户登录时记录下来并节省时间.例如:

//LoginScreen
import { onSignIn } from '../actions/auth'; //I will describe the onSignInMethod below
import axios from 'axios'; //lets use axios. You may use fetch too.


export default class LoginScreen extends Component {


    //your code: state, static etc
    loginMethod = () => {
        const url = yourauthUrl;
        const payload = {
            email: this.state.email,
            password: this.state.password
        };
        axios.post(url, payload)
        .then((response) => {
            if (response.status == 200) {
                const dateOfLastLogin = new Date().getTime().toString(); //take note of the time the user logs in.
                AsyncStorage.setItem('dateOfLastLogin', dateOfLastLogin);
            }
        })
        .then(() => { 
            onSignIn() //onSignIn handles your sign in. See below.
            .then(() => this.props.navigation.navigate('AfterSignInPage'));
            })
            .catch(() => { // your callback if onSignIn Fails
            });
        })
        .catch((error) => { //your callback if axios fails
        });
    }

}

在../actions/auth.js中

import { AsyncStorage } from 'react-native';

export const onSignIn = () => AsyncStorage.setItem('auth_key', 'true');
//in LoginScreen we called this to set that a user has successfully logged in
//why is true a string? -- Because Asyncstorage stores only strings

export const onSignOut = () => AsyncStorage.multiRemove(['auth_key', 'dateOfLastLogin']);

//now lets create a method that checks if the user is logged in anytime
export const isSignedIn = () => {
    return new Promise((resolve, reject) => {
        AsyncStorage.multiGet(['auth_key', 'dateOfLastLogin'])
        .then((res) => {
            const userKey = res[0][1];
            const lastLoginDate = parseInt(res[1][1]);
            const today = new Date().getTime();
            const daysElapsed = Math.round(
                (today - lastLoginDate) / 86400000
                );
            if (userKey !== null && (daysElapsed < 14)) {
                resolve(true);
            } else {
                resolve(false);
            }
        })
        .catch((err) => reject(err));
    });
};

现在我们可以从’../actions/auth’导入{isSignedIn};从我们的任何组件中使用,并像这样使用它:

isSignedIn()
    .then((res) => {
        if (res) { 
            // user is properly logged in and the login keys are valid and less than 14 days 
        }
    })

///////////////////////////////////////////////////// ///////////////////////////

如果您想使用redux

在Redux中处理登录

在你的types.js中

//types.js
export const LOGGED_IN = 'LOGGED_IN';

在您的还原动作中

//loginActions.js
import {
    LOGGED_IN,
} from './types';

export function login() {
    let dateOfLastLogin = null;
    let isLoggedIn = 'false';
    AsyncStorage.multiGet(['auth_key', 'dateOfLastLogin'])
    .then((res) => {
        isLoggedIn = res[0][1];
        dateOfLastLogin = parseInt(res[1][1]);
    }); //note this works asynchronously so, this may not be a good approach
    return {
        type: LOGGED_IN,
        isLoggedIn, 
        dateOfLastLogin
    };
}

在您的loginReducer中

//LoginReducer.js
import {
    LOGGED_IN
} from '../actions/types';


const initialState = {
    userIsLoggedIn: false
};

export function loginReducer(state=initialState, action) {
    switch (action.type) {

        case LOGGED_IN:

            const userKey = action.isLoggedIn;
            const lastLoginDate = action.dateOfLastLogin;
            const today = new Date().getTime();
            const daysElapsed = Math.round(
                (today - lastLoginDate) / 86400000
                );
            let trulyLoggedIn = false;
            if (userKey !== null && (daysElapsed < 14)) {
                trulyLoggedIn = true;
            } else { trulyLoggedIn = false }
            return {
                userIsLoggedIn: trulyLoggedIn
            };

        default:
            return state;
    }
}

在您的./reducers/index.js中

//reducers index.js
import { combineReducers } from 'redux';

import { loginReducer } from './LoginReducers';

const rootReducer = combineReducers({
    loggedIn: loginReducer
});

export default rootReducer;

在使用redux-thunk的商店中,套用applyMiddleWare.让我们称之为configureStore.js

//configureStore.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';

export default function configureStore(initialState) {
    return createStore(
        rootReducer,
        initialState,
        applyMiddleware(thunk)
    );
}

在您的App.js中

//App.js
import { Provider } from 'react-redux';
import configureStore from './src/store/configureStore'; //where you configured your store
import { YourMainNavigator } from '../src/config/router'; //where your root navigator is

const store = configureStore();
export default class App extends Component<{}> {
    render() {
        return (
            <Provider store={store}>
                <YourMainNavigator />
            </Provider>
        );
    }
}

您应该知道您不再需要auth.js中的isSignedIn方法
您的登录方法与上面在LoginScreen中概述的相同.

现在,您可以使用redux来检查登录状态,如下所示:

import React, {Component} from 'react';
import {connect} from 'react-redux';

class MyComponent extends Component {
    someFunction() {
        if (this.props.loggedIn) {
            //do something
        }
    }
}
const mapStateToProps = (state) => {
    return {
        loggedIn: state.loggedIn.userIsLoggedIn
    };
}


export default connect(mapStateToProps)(MyComponent);

应该有一种使用redux来管理登录的更好方法-比我在这里概述的要好.我认为您也可以使用redux来管理登录状态,而无需使用AsyncStorage.您需要做的只是在loginScreen中,如果登录函数返回response.status ==’ok’,则可以将操作分派到redux以登录用户.在上面的示例中,使用asyncstorage您可能只需要使用redux检查用户是否已登录.

上一篇:javascript-如何读取输入,然后通过屏幕阅读器标记?


下一篇:javascript-如何在一个屏幕而不是整个应用程序中处理退出应用程序-React Native?