在存储操作完成之前,React Native + Redux组件呈现

时间:2016-08-31 16:31:49

标签: react-native redux

我已经使用redux对本机应用程序做出反应,用户在成功登录后会被归为主组件。但是在通过商店接收用户配置文件之前,主组件会被渲染。如果我使用'Home'组件作为连接组件,那么在重新渲染时它会接收配置文件。

这是一个正确的流程,还是我可以延迟'Home'的渲染,直到商店填充新数据。

这是代码

类型

BUNDLE_LOGIC

减速

export const FETCH_PROFILE = 'FETCH_PROFILE';
export const UPDATE_PROFILE = 'UPDATE_PROFILE';
export const DELETE_PROFILE = 'DELETE_PROFILE';
export const FETCH_STREAMS = 'FETCH_STREAMS';

操作

export default function profile(state = {}, action) {

  switch (action.type) {

  case types.FETCH_PROFILE:

    return {
      ...state,
      profile: action.profile
    }

  case types.UPDATE_PROFILE:

    return {
      ...state,
      profile: action.profile
    }

  case types.DELETE_PROFILE:

    return {
      ...state,
      profile: null
    };

  default:
    return state;
  }
}

登录组件

var PROFILE_KEY = "@myApp:profile";

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

export function updateProfile(data) {
  return dispatch => {
    AsyncStorage.setItem(PROFILE_KEY, JSON.stringify(data))
      .then(() => {
        dispatch({
          type: types.UPDATE_PROFILE,
          profile: data
        })
      })
  }
}

export function deleteProfile() {
  return dispatch => {
    AsyncStorage.removeItem(PROFILE_KEY)
      .then(() => {
        dispatch({
          type: types.DELETE_PROFILE
        })
      })
  }
}

主页

class Login extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      username: "",
      password: "",
      error: "",
      showProgress: false,
    };
  }

  _focusNextField(nextField) {
    this.refs[nextField].focus();
  }

  _onLoginPressed() {
    this.setState({showProgress: true});
    this._login();
  }

  async _login() {
    try {
      let response = await fetch( BASE_URL + url, {
                             method: 'POST',
                             headers: {
                               'Accept': 'application/json',
                               'Content-Type': 'application/json',
                             },
                             body: JSON.stringify({
                               user: {
                                 email: this.state.username,
                                 password: this.state.password,
                               }
                             })  
                           });

      let res = await response.text();
       if (response.status >= 200 && response.status < 300) {
          let user = JSON.parse(res);
          this.props.updateProfile(user.user);
          this.setState({showProgress: false});
          this.props.navigator.replace({name: 'Home'});
       }
       else {
         let error = JSON.parse(res);
         throw error.errors;
       }
    } catch(error) {
        this.setState({error: error});
        this.setState({showProgress: false});
        console.log("error " + error);
    }
  }

  render() {
    return (
        <View style={styles.loginBox}>
          <TextInput
            ref="username"
            value={this.state.username}
            placeholder="Username" 
            keyboardType="email-address"
            onChangeText={(username) => this.setState({username}) }
            onSubmitEditing={() => this._focusNextField('password')}/> 
          <TextInput 
            ref="password"
            placeholder="Password" 
            value={this.state.password}
            secureTextEntry={true} 
            onChangeText={(password) => this.setState({password}) }
            returnKeyType="go"/>
          <Button textStyle={{fontSize: 14}} onPress={this._onLoginPressed.bind(this)} style={{marginTop: 30}}>
            Sign In
            </Button>
        </View>
      );
  }
}

const styles = StyleSheet.create({
  loginBox: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    alignItems: 'stretch',
    margin: 10,
  }
});

var {updateProfile} = require('../Actions');
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

module.exports = connect(
  null,
  (dispatch) => {
    return bindActionCreators({updateProfile}, dispatch)
  }
)(Login)

1 个答案:

答案 0 :(得分:2)

If you're using redux-thunk, you can delay the transition until data is loaded. You need to change some small things.

Add return to action creator.

export function updateProfile(data) {
  return dispatch => {
    return AsyncStorage.setItem(PROFILE_KEY, JSON.stringify(data))
      .then(() => {
        dispatch({
          type: types.UPDATE_PROFILE,
          profile: data
        })
      })
  }
}

add await

if (response.status >= 200 && response.status < 300) {
  let user = JSON.parse(res);
  await this.props.updateProfile(user.user);
  this.setState({showProgress: false});
  this.props.navigator.replace({name: 'Home'});
}