2016-08-30 16 views
0

我是新来对native + redux做出反应的。我有一个反应本机应用程序,其中用户的第一个屏幕是登录和登录后显示从服务器的类别列表的页面。要获取类别列表,需要传递身份验证令牌,我们从登录屏幕获取身份验证令牌,或者先前从AsyncStorage登录后才能获取身份验证令牌。在任何组件渲染之前使用数据反应native + redux填充存储区

所以在重组任何组件之前,我正在创建存储和manully分派fetchProfile()这样的操作。

const store = createStore(reducer); 
store.dispatch(fetchProfile()); 

因此,fetchProfile()尝试从AsyncStorage中读取配置文件数据并使用数据调度操作。

export function fetchProfile() { 
    return dispatch => { 
     AsyncStorage.getItem('@myapp:profile') 
     .then((profileString) => { 
      dispatch({ 
      type: 'FETCH_PROFILE', 
      profile: profileString ? JSON.parse(profileString) : {} 
      }) 
     }) 
    } 
    } 

所以在商店被填充之前,登录页面被渲染。因此,使用react-redux的连接方法,我订阅存储更改并有条件地加载登录页面。

class MyApp extends React.Component { 
    render() { 
     if(this.props.profile) 
     if(this.props.profile.authentication_token) 
      retunr (<Home />); 
    else 
      return (<Login />); 
     else 
     return (<Loading />); 
    } 
    } 

    import { connect } from 'react-redux'; 

    const mapStateToProps = (state) => { 
    return { 
     profile: state.profile 
    } 
    } 

    module.exports = connect(mapStateToProps, null)(MyApp); 

因此,首先'Loading'组件被渲染,当存储被填充时,'Login'或'Home'组件被渲染。那它是一个正确的流程吗?或者有什么办法可以在任何compnent渲染之前首先获得存储区,而不是渲染'Loading'组件,我可以直接渲染'Login'或'Home'组件。

回答

1

VERRY常见的方法是有3个动作用于异步操作

types.js

export const FETCH_PROFILE_REQUEST = 'FETCH_PROFILE_REQUEST'; 
export const FETCH_PROFILE_SUCCESS = 'FETCH_PROFILE_SUCCESS'; 
export const FETCH_PROFILE_FAIL = 'FETCH_PROFILE_FAIL'; 

actions.js

import * as types from './types'; 

export function fetchProfile() { 
    return dispatch => { 
    dispatch({ 
     type: types.FETCH_PROFILE_REQUEST 
    }); 
    AsyncStorage.getItem('@myapp:profile') 
     .then((profileString) => { 
     dispatch({ 
      type: types.FETCH_PROFILE_SUCCESS, 
      data: profileString ? JSON.parse(profileString) : {} 
     }); 
     }) 
     .catch(error => { 
     dispatch({ 
      type: types.FETCH_PROFILE_ERROR, 
      error 
     }); 
     }); 
    }; 
} 

reducer.js

import {combineReducers} from 'redux'; 
import * as types from './types'; 

const isFetching = (state = false, action) => { 
    switch (action.type) { 
    case types.FETCH_PROFILE_REQUEST: 
     return true; 
    case types.FETCH_PROFILE_SUCCESS: 
    case types.FETCH_PROFILE_FAIL: 
     return false; 
    default: 
     return state; 
    } 
}; 

const data = (state = {}, action) => { 
    switch (action.type) { 
    case types.FETCH_PROFILE_SUCCESS: 
     return action.data; 
    } 
    return state; 
}; 

export default combineReducers({ 
    isFetching, 
    data 
}); 

所以你可以在你的组件和显示/隐藏Loader组件

+0

上述问题中的代码是做同样的事情,但只是想确保它是我正确的方式吗?由于商店在折叠后被填充。因此渲染首先发生(直到加载组件),然后Store由fetchProfile填充,触发重新渲染,然后进入Login或Home。所以可以在任何组件呈现之前从AsyncStorage预先填充存储数据。 –

+1

这是可能的,但然后你会显示用户一个空白的屏幕。如果你有一个异步操作,通常让用户知道应用程序正在加载并显示'Loader'组件。所以你选择了一个正确的方法。我只是重构了一下你的代码。 –

0

您可以在开机画面中加载的所有数据,然后之后加载其他屏幕isFetching道具。我是这样做的。希望它有帮助

class Root extends Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
      isLoading: true, 
      store: configureStore(async() => { 

       const user = this.state.store.getState().user || null; 

       if (categories && categories.list.length < 1) { 
        this.state.store.dispatch(categoriesAction()); 
       } 
       this.setState({ 
        isLoading: false 
       }); 

      }, initialState) 
     }; 
    } 


    render() { 
     if (this.state.isLoading) { 
      return <SplashScreen/>; 
     } 
     return (
      <Provider store={this.state.store}> 
       <AppWithNavigationState /> 
      </Provider> 
     ); 
    } 
}