J'ai un écran avec des tâches que je récupère à partir d'une API. Dans mon écran, je souhaite afficher un message jusqu'à ce que les travaux soient récupérés, puis les afficher à l'écran. Je déclenche la récupération des travaux dans componentDidMount (), puis j'essaye de les afficher dans RenderJobs (). Le problème est que props.isLoading n'est pas défini pour une raison quelconque.
J'utilise des valeurs codées en dur pour l'appel API pour le moment. Une fois que j'aurai les données à afficher correctement, je changerai cela.
Voici mon JobsComponent:
export const fetchJobs = (address, job) => async (dispatch) => { dispatch(jobsLoading()); var obj = {"origin": [26.1410638, 44.4346588], "job_details": ["Developer"]}; //fetch the data .then(response => response.json()) .then(jobs => dispatch(addJobs(jobs))) .catch(error => dispatch(jobsFailed(error.message))); }; export const addJobs = (jobs) => ({ type: ActionTypes.GET_JOBS, payload: jobs }); export const jobsLoading = () => ({ type: ActionTypes.JOBS_LOADING }); export const jobsFailed = (errmess) => ({ type: ActionTypes.JOBS_FAILED, payload: errmess });
Ceci est mon réducteur: p >
import * as ActionTypes from '../ActionTypes'; export const jobs = (state = { isLoading: true, errMess: null, jobs:[]}, action) => { switch (action.type) { case ActionTypes.GET_JOBS: return {...state, isLoading: false, errMess: null, jobs: action.payload}; case ActionTypes.JOBS_LOADING: return {...state, isLoading: true, errMess: null, jobs: []} case ActionTypes.JOBS_FAILED: return {...state, isLoading: false, errMess: action.payload}; default: return state; } };
Et voici le créateur de l'action:
import React, {Component} from 'react'; import {connect} from 'react-redux'; import {fetchJobs} from '../redux/ActionCreators'; const mapStateToProps = state => { return { jobs: state.jobs } } const mapDispatchToProps = dispatch => ({ fetchJobs: (address, jobTitle) => dispatch(fetchJobs(address, jobTitle)) }); function RenderJobs(props) { console.log('In RenderJobs, props is: ' + props.jobsData + ' / ' + props.isLoading); const renderJobItem = ({item, index}) => { return ( //UI view to show data ); } if (props.isLoading) { return ( <View> <Text style={{fontSize: 30, color: colors.white}}>The data is loading...</Text> </View> ); } else if (props.errMess) { return( <View> <Text style={{fontSize: 30, color: colors.white}}>{props.errMess} </Text> </View> ); } else { return ( //UI view to show data ); } } class Jobs extends Component { componentDidMount() { this.props.fetchJobs([26.1410638, 44.4346588], "Developer"); } render() { return( <ScrollView contentContainerStyle={styles.bkg}> <RenderJobs jobsData={this.props.jobs} isLoading={this.props.jobs.isLoading} errMess={this.props.jobs.errMess} /> </ScrollView> ) } }
Je m'attends à ce que deux choses se produisent.
Dans la fonction RenderJobs (), je compte sur props.isLoading pour me donner l'état de chargement. Cependant, il n'est pas défini. Je peux voir dans les journaux que l'action JOBS_LOADING est distribuée et que les données des travaux sont correctement récupérées.
Une fois les données des travaux récupérées, je m'attends à les afficher dans l'interface utilisateur. Cependant, ce n'est pas le cas - je vois juste un écran vide.
Toute aide sera grandement appréciée!
3 Réponses :
Il semble que vous ayez oublié d'ajouter isLoading
dans votre mapStateToProps
.
isLoading
sera indéfini lors du premier rendu car vous n'avez défini aucune valeur par défaut. Vous pouvez fournir une valeur par défaut à l'aide des accessoires par défaut.
Jobs.defaultProps = { jobs: { isLoading: false } }
Cela fonctionne bien, dans le sens où si je définis isLoading: true dans les accessoires par défaut, l'écran affiche le message de chargement que je souhaite. Le problème est que, une fois que les travaux sont extraits de l'API, ils ne sont pas affichés dans l'interface utilisateur (l'interface utilisateur reste bloquée avec le message de chargement). Des idées pourquoi?
Je ne sais pas où vous appelez la méthode de connexion. Vous devez déboguer et ajouter un point d'arrêt dans mapStateToProps
, lorsque l'appel de l'API est terminé et que la récupération est terminée, les mises à jour du réducteur stockent, en raison de la méthode de connexion, le composant Jobs
sera de nouveau rendu -> mapStateToProps
sera à nouveau appelé avec les accessoires mis à jour (jobs.isLoading comme false)
La méthode de connexion est appelée à la fin de mon fichier .js - exporter la connexion par défaut (mapStateToProps, mapDispatchToProps) (Jobs); Je vais essayer d'ajouter les points d'arrêt que vous avez mentionnés et vous informer du résultat.
J'ai découvert quel était le problème. Dans mon configureStore.js, j'avais oublié d'ajouter le réducteur de jobs au magasin. Merci à tous pour vos réponses!
import {jobTitles} from './reducers/jobTitles'; import {jobs} from './reducers/jobs'; import {persistStore, persistCombineReducers} from 'redux-persist'; import storage from 'redux-persist/es/storage'; export const ConfigureStore = () => { const config = { key: 'root', storage, debug: true }; const store = createStore( persistCombineReducers(config, { jobTitles, jobs //I added this line and it fixed the problem! }), applyMiddleware(thunk, logger) ); const persistor = persistStore(store); return {persistor, store}; }
Pourquoi ne définissez-vous pas la valeur de l'indicateur
isLoading
comme false à partir des accessoires par défaut. De cette façon,isLoading
sera faux dans le premier rendu et pourra ensuite être mis à jour en distribuant une action,Je ne suis pas vraiment sûr de comprendre ce que vous entendez par "accessoires par défaut". Pourriez-vous donner un exemple de code, s'il vous plaît? De plus, l'action de chargement est distribuée dans le créateur d'action dans la fonction fetchJobs ().