【问题标题】:React native + redux populate store with data before any Component renderReact native + redux 在任何组件渲染之前使用数据填充存储
【发布时间】:2017-01-06 10:05:13
【问题描述】:

我是反应原生 + redux 的新手。我有一个反应本机应用程序,其中用户第一个屏幕是登录,登录后显示来自服务器的类别列表页面。要获取类别列表需要传递身份验证令牌,我们从登录屏幕获取,或者如果他之前登录过,则从 AsyncStorage 获取。

所以在重新设计任何组件之前,我正在创建商店并像这样手动调度 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 的 connect 方法,我订阅了存储更改并有条件地加载登录页面。

 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);

所以首先渲染“加载”组件,然后在填充存储时渲染“登录”或“主页”组件。那么它是一个正确的流程吗?或者有没有一种方法可以在任何组件渲染之前先填充存储,而不是渲染“加载”组件,我可以直接渲染“登录”或“主页”组件。

【问题讨论】:

    标签: reactjs react-native redux react-redux


    【解决方案1】:

    非常常见的方法是为异步操作设置 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
    });
    

    所以你可以在你的组件中获取isFetching prop 并显示/隐藏加载器组件

    【讨论】:

    • 上述问题中的代码正在做同样的事情,但只是想确保我这样做是否正确?由于商店在出租后被填充。所以渲染首先发生(直到加载组件)然后由 fetchProfile 填充存储,触发重新渲染,然后进入登录或主页。因此,可以在任何组件渲染之前从 AsyncStorage 预填充存储数据。
    • 这是可能的,但你会向用户显示一个空白屏幕。如果您有异步操作,通常最好让用户知道应用正在加载并显示Loader 组件。所以你选择了正确的方法。我只是稍微重构了你的代码。
    【解决方案2】:

    您可以在初始屏幕期间加载所有数据,然后再加载其他屏幕。我是这样做的。希望对你有帮助

    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>
            );
        }
    }
    

    【讨论】:

      【解决方案3】:

      Redux 和 Redux Persist (https://github.com/rt2zz/redux-persist) 将解决您的问题。 不要让它们变得复杂。

      【讨论】:

        猜你喜欢
        • 2017-07-23
        • 1970-01-01
        • 2020-09-13
        • 2019-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-05
        • 1970-01-01
        相关资源
        最近更新 更多