2016-08-30 1 views
0

네이티브 + 리듀 스를 사용하는 새로운 방법입니다. 나는 사용자가 첫 화면을 로그인하고 로그인 후 서버에서 카테고리 목록의 페이지를 보여주는 반응 네이티브 응용 프로그램이 있습니다. 카테고리 목록을 가져 오려면 인증 토큰을 전달해야합니다. 인증 토큰은 로그인 화면에서 가져 오거나 이전에 AsyncStorage에서 로그인 한 경우에 전달됩니다.네이티브 + 리듀 스 (native + redux) 데이터를 저장소로 보내기 전에 어떤 데이터를 저장 하시겠습니까?

그래서 어떤 구성 요소를 redering하기 전에 나는 store와 manully dispatching 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); 

첫 번째 '로드 중'구성 요소가 렌더링되고 저장소가 채워지면 '로그인'또는 '홈'구성 요소가 렌더링됩니다. 그래서 올바른 흐름입니까? 아니면 어떤 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'; 

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

을 actions.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

위의 질문에있는 코드는 똑같은 일을하고 있지만, 제가 올바르게하고 있는지 확인하고 싶습니다. 상점은 렌딩 후 채워집니다. 따라서 렌더링이 먼저 발생하고 (로드 컴포넌트까지) fetchProfile에 의해 Store가 생성되어 다시 렌더링을 시작한 다음 로그인 또는 홈으로 이동합니다. 따라서 구성 요소를 렌더링하기 전에 AsyncStorage에서 저장 데이터를 미리 채울 수 있습니다. –

+1

가능하지만 사용자에게 빈 화면이 표시됩니다. 일반적으로 비동기 액션이있는 경우 사용자에게 앱이로드되고 '로더'구성 요소가 표시된다는 사실을 알리는 것이 좋습니다. 그래서 당신은 올바른 접근 방식을 선택했습니다. 방금 코드를 리팩토링했습니다. –

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