2016-08-31 6 views
0

난 네비게이션 네이티브 응용 프로그램에 반응했습니다. 여기서 성공적으로 로그인하면 사용자는 집에 돌아 가지 않습니다. 그러나 홈 구성 요소는 상점을 통해 사용자 프로파일을 수신하기 전에 렌더링됩니다. 연결 컴포넌트로 'Home'컴포넌트를 사용하면 다시 렌더링 할 때 프로파일을받습니다.React Native + Redux 구성 요소가 저장 작업 완료 전에 렌더링됩니다.

올바른 흐름이거나 저장소에 새로운 데이터가 채워질 때까지 '집'의 렌더링을 지연시킬 수 있습니까? 여기

코드입니다

유형

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) 

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

왜 그냥'에서 바쁜 스피너를 표시하지 않는 추가의'문제를 단지 자연 반응 비동기 소프트웨어 – Maxwelll

+0

나는 다시하고있다. 그러나 에서 또 다른 api 콜을하기 위해 필자가 필요로하는 다른 컴포넌트를 rending했다. 어느 것이 조금 어려워 질 것입니다. 그러나 주어진 해결책은 정말로 굉장했고 @caojs에 감사했습니다. –

답변

2

당신이 redux-thunk을 사용하는 경우 전환을 지연시킬 수 있습니다. 작은 일을 좀 바꿔야합니다.

액션 작성자에게 return을 추가하십시오. 구성 요소가 정말 필요한 데이터 ... 이러면를받을 때까지

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

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'}); 
} 
관련 문제