2016-08-30 5 views
0

Ich bin neu zu reagieren native + Redux. Ich habe eine reaktionsnative Anwendung, wo Benutzer zuerst Bildschirm ist Login und nach Login zeigt Seite der Liste der Kategorien von Server. Um eine Liste von Kategorien abzurufen, müssen Sie das Authentifizierungstoken übergeben, das wir vom Anmeldebildschirm erhalten, oder wenn Sie sich zuvor von AsyncStorage angemeldet haben.React native + redux Populationsspeicher mit Daten vor allen Komponenten Render

Bevor ich also eine Komponente reedere, erstelle ich einen Store und beende die fetchProfile() Aktion so.

const store = createStore(reducer); 
store.dispatch(fetchProfile()); 

So fetchProfile() versucht, lesen Profildaten aus AsyncStorage und Versand Aktion mit Daten.

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

so vor Laden ausgefüllt werden, Login-Seite gerendert werden. Mit der connect-Methode von react-redux abonniere ich Speicheränderungen und lade die Anmeldeseite bedingt.

Zuerst wird die Komponente 'Loading' gerendert und wenn der Speicher gefüllt ist, wird entweder 'Login' oder 'Home' gerendert. Also ist es ein richtiger Fluss? Oder gibt es einen Weg, auf dem ich Speicher zuerst bevölkert bekommen kann, bevor irgendein Compnent rendert, und anstatt 'Loading' zu rendern, kann ich 'Login' oder 'Home' Component direkt rendern.

Antwort

1

Verry gemeinsamer Ansatz 3 Aktionen

types.js für einen Asynchron-Betrieb hat

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

So können Sie isFetching prop in Ihrer Komponente und zeigen/verstecken Loader-Komponente

+0

Code in obiger Frage tut die gleiche Sache, aber will nur sicherstellen, dass es ich mache es richtig? Da der Store nach dem Rendern gefüllt wird. Das Rendering erfolgt also zuerst (bis zum Laden der Komponente), dann wird Store von fetchProfile aufgefüllt, was das erneute Rendern auslöst und dann zu Login oder Home geht. Daher ist es möglich, Speicherdaten aus AsyncStorage vor dem Rendern von Komponenten vorab aufzufüllen. –

+1

Es ist möglich, aber dann zeigen Sie dem Benutzer einen leeren Bildschirm. Wenn Sie eine asynchrone Aktion haben, ist es normalerweise viel besser, den Benutzer wissen zu lassen, dass die App geladen wird und die 'Loader'-Komponente anzeigt. Also hast du einen richtigen Ansatz gewählt. Ich habe deinen Code ein wenig überarbeitet. –

0

erhalten Sie können während der Splash-Screen alle Ihre Daten laden und dann die anderen Bildschirme danach zu laden. Ich habe es so gemacht. Hoffe, es hilft

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