2016-08-31 6 views
0

Ich habe native Anwendung mit Redux reagieren, wo Benutzer nach erfolgreichem Login zu Hause Komponente genvigiert werden. Aber die Home-Komponente wird gerendert, bevor sie das Benutzerprofil über den Store erhält. Wenn ich die "Home" -Komponente als verbundene Komponente verwende, wird sie beim erneuten Rendern als Profil angezeigt.React Native + Redux-Komponente rendert, bevor Store Aktion abgeschlossen ist

Es ist ein korrekter Ablauf oder kann ich das Rendering von 'Home' verzögern, bis der Speicher mit neuen Daten gefüllt ist.

Hier Code

Typen

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

Reducer

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

Aktionen

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

Anmeldung Component

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) 

Startseite

class Home extends React.Component { 

    render() { 
    return (
     <View style={{flex: 1, backgroundColor: '#fff'}}> 
     <Text style={{margin: 10, fontSize: 15, textAlign: 'left'}}>I'm in the Drawer!</Text> 
     <Text>Auth key : {this.props.profile ? this.props.profile.authentication_token : 'authentication_token'}</Text> 
     </View> 
    ); 
    } 
} 

//module.exports = Home; 

import { connect } from 'react-redux'; 

module.exports = connect(
    (state) => { 
    return { 
     profile: state.profile 
    } 
    }, 
    null 
)(Home) 
+0

Warum gehst du nicht einfach in '' ein Besetzt Spinner angezeigt, bis die Komponente, die die Daten empfängt, braucht es ... Dies ist nicht wirklich ein Problem reagieren nur die Art der asynchrone Software – Maxwelll

+0

Ich mache, aber wieder in Ich war eine andere Komponente zerbrechen, für die ich Profil für einen anderen API-Aufruf erforderlich war. Was etwas schwierig wurde. Aber gegebene Lösung war wirklich großartig und danke an @ caojs –

Antwort

2

Wenn Sie redux-thunk verwenden sind, können Sie den Übergang verzögern, bis die Daten geladen wird. Sie müssen einige kleine Dinge ändern.

Fügen Sie return zu Aktionsersteller hinzu.

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

hinzufügen 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'}); 
} 
Verwandte Themen