Je suis une relativité nouvelle pour réagir/redux. Là, je veux poser une question (peut-être philosophique).
Est-il correct d'envoyer une action (par exemple pour déclencher un appel api) sur componentDidMount
d'un composant React?
Sinon, pourquoi et où dois-je envoyer l'action?
Si oui, alors plus de questions? :)
Oui, l'envoi d'une action sur componentDidMount()
est OK, et même la chose recommandée à faire car cela ne ralentira pas le rendu initial de l'interface utilisateur.
Étant donné que la fonction s'exécute après le rendu initial du composant, gardez à l'esprit que vous pouvez avoir entre le moment où le composant est rendu et le moment où vous recevez les données de l'appel api.
Oui, vous devez certainement utiliser le crochet componentDidMount.
Un cas d'utilisation typique pourrait être:
Je sais que c'est un peu long, mais je travaillais moi-même sur ce type de problème depuis un moment, alors j'ai pensé partager le schéma suivant;)
Lorsque le composant monte, une action d'extraction de données est déclenchée. Une valeur 'isFetching' dans l'état de l'application détermine si le spinner est affiché ou non (je pense que j'ai utilisé 'advanced-loader' ou une telle bibliothèque)
export default class MyComponent extends React.Component {
componentDidMount() {
AppDispatcher.dispatch({
type: ActionTypes.FETCH_DATA,
});
}
render() {
let isFetching = this.props.my.application.path.isFetching;
return (
<Loader show={isFetching} message={'loading'}>
<div>
My Component
</div>
</Loader>
);
}
}
Puis dans le magasin le FETCH_DATA déclenche une requête:
class AppStore extends ReduceStore {
//......
reduce(state, action) {
let imState = Immutable.fromJS(state);
switch (action.type) {
//......
case ActionTypes.FETCH_DATA:
doGetRequest('/url_to_service');
break;
//......
}
return imState.toJS();
}
}
La demande ressemblerait à quelque chose comme ceci:
function doGetRequest(endpoint, params = {}) {
//request is some kind of AJAX library. In my case 'superagent'
request.get(endpoint)
.set('Accept','application/json')
.query(params)
.end(
(err, res) => {
if (res && res.ok) {
receiveData(endpoint, "SUCCESS", res);
} else {
receiveData(endpoint, "FAIL");
}});
}
Une fois terminé, il enverrait alors une autre action.
function receiveData(endpoint, state, responseData) {
AppDispatcher.dispatch(
{
type: ActionTypes.SERVER_RESPONSE,
endpoint: endpoint,
state: state,
payload: responseData
}
);
}
Pour revenir au magasin, la deuxième action est interceptée et l'indicateur isFetching est défini sur false, puis les données d'application sont traitées.
reduce(state, action) {
let imState = Immutable.fromJS(state);
switch (action.type) {
//......
case ActionTypes.SERVER_RESPONSE: {
imState = imState.setIn(['my','application','path', 'isFetching'], false)
if (action.state == "SUCCESS") {
//do something with the action.response data (via state update)
}else if (action.state == "FAIL") {
//maybe show an error message (via state update)
}
break;
}
}
return imState.toJS();
}
}
.... donc ce cas d'utilisation typique utilise deux "actions", la première action étant déclenchée à partir de la méthode componentDidMount, et la deuxième action est déclenchée une fois la demande terminée.
J'espère que ce modèle vous aidera :)
Selon la documentation officielle React, componentDidMount
est exactement le bon endroit pour le faire:
componentDidMount () est appelé immédiatement après le montage d'un composant. L'initialisation qui nécessite des nœuds DOM devrait aller ici. Si vous devez charger des données à partir d'un point de terminaison distant, c'est un bon endroit pour instancier la demande réseau.
Lors de l'utilisation de routes, une autre méthode recommandée pour envoyer une action serait la méthode routes "onEnter". Ceci afin de rendre le composant non dépendant des actions (ou appels api).
Personnellement, je pense que les deux méthodes (componentDidMount vs onEnter) sont correctes. Il appartient au programmeur de choisir la solution la mieux adaptée à son application.