2017-08-04 1 views
0

J'essaie d'enrouler ma tête autour de l'accès à l'état dans Redux actionCreators; à la place a fait ce qui suit (opération ajax effectuée dans le réducteur). Pourquoi ai-je besoin d'accéder à l'état pour cela - parce que je veux effectuer ajax avec un jeton CSRF stocké dans l'état.Effectuez Ajax Fetch dans un Redux Reducer?

Quelqu'un pourrait-il s'il vous plaît me dire si ce qui suit est considéré comme une mauvaise pratique/anti-modèle?

export const reducer = (state = {} , action = {}) => { 

    case DELETE_COMMENT: { 

     // back-end ops 
     const formData = new FormData(); 
     formData.append('csrf' , state.csrfToken); 
     fetch('/delete-comment/' + action.commentId , { 
      credentials:'include' , 
      headers:new Headers({ 
       'X-Requested-With':'XMLHttpRequest' 
      }) , 
      method:'POST' , 
      body:formData 
     }) 

     // return new state 
     return { 
      ...state , 
      comments:state.comments.filter(comment => comment.id !== action.commentId) 
     }; 
    } 

    default: { 
     return state; 
    } 
} 

Répondre

2

De la documentation redux:

La seule façon de changer l'état est d'émettre une action, un objet décrivant ce qui est arrivé. Ne mettez pas les appels d'API dans les réducteurs. Réducteurs sont simplement des fonctions pures qui prennent l'état précédent et une action, et retournent l'état suivant. N'oubliez pas de renvoyer de nouveaux objets d'état, au lieu de modifier l'état précédent.

Les actions doivent décrire le changement. Par conséquent, l'action doit contenir les données pour la nouvelle version de l'état, ou au moins spécifier la transformation qui doit être effectuée. En tant que tel, les appels d'API doivent aller dans des actions asynchrones qui distribuent des actions pour mettre à jour l'état. Les réducteurs doivent toujours être purs et ne pas avoir d'effets secondaires. Pour plus d'informations, consultez async actions.

Un exemple d'une action async des exemples de Redux:

function fetchPosts(subreddit) { 
    return (dispatch, getState) => { 
     // contains the current state object 
     const state = getState(); 

     // get token 
     const token = state.some.token; 

     dispatch(requestPosts(subreddit)); 

     // Perform the API request 
     return fetch(`https://www.reddit.com/r/${subreddit}.json`) 
      .then(response => response.json()) 

      // Then dispatch the resulting json/data to the reducer 
      .then(json => dispatch(receivePosts(subreddit, json))) 
    } 
} 
+0

Merci beaucoup de précisions de votre & @ WitVault, ce que vous dit tous les deux fait beaucoup de sens.J'ai réalisé des actions asynchrones avec thunk; mais, ce que je ne peux pas comprendre est, comment puis-je faire un api appel (fetch), mais ajouter des données de l'état dans mes vars POST lors de la récupération? Par exemple: un jeton CSRF? – sammysaglam

+1

@sammysaglam consultez la réponse mise à jour. Vous pouvez avoir un second paramètre qui est une fonction 'getState', qui retournera l'objet d'état de base. – Matthew

+0

qui a fonctionné! incroyable! Merci beaucoup! J'essayais de comprendre cela pour une bonne heure maintenant! – sammysaglam

4

Conformément aux lignes directrices de Redux.

Il est très important que le réducteur reste pur. Choses que vous ne devriez jamais faire à l'intérieur d'un réducteur:

  • Mutation de ses arguments;
  • Perform des effets secondaires comme des appels API et des transitions de routage;
  • appeler des fonctions non-pur, par exemple, Date.now() ou Math.random().

Si vous demandez si c'est anti-pattern ou pas alors oui c'est absolument.

Mais si vous demandez quelle est la solution.

  1. Ici, vous devez envoyer async action de votre action-créateurs
  2. Utilisez "Redux-thunk" ou "Redux-saga" pour que
  3. Vous pouvez accéder à l'état et créer une action async

par exemple dans votre-créateur d'action (par exemple seulement)

export function deleteCommment(commentId) { 
    return dispatch => { 
     return Api.deleteComment(commentId) 
      .then(res => { 
       dispatch(updateCommentList(res)); 
      }); 
    }; 
} 

export function updateCommentList(commentList) { 
    return { 
     type : UPDATE_COMMENT_LIST, 
     commentList 
    }; 
} 

Edit: Vous pouvez accéder à l'état -

export function deleteCommment(commentId) { 
    return (dispatch, getState) => { 
     const state = getState(); 
     // use some data from state 
     return Api.deleteComment(commentId) 
      .then(res => { 
       dispatch(updateCommentList(res)); 
      }); 
    }; 
} 
+0

Merci beaucoup pour votre clarification & @ Matthew, ce que vous avez dit tous les deux a beaucoup de sens. J'ai réalisé des actions asynchrones avec thunk; mais, ce que je ne peux pas comprendre est, comment puis-je faire un api appel (fetch), mais ajouter des données de l'état dans mes vars POST lors de la récupération? Par exemple: un jeton CSRF? – sammysaglam

+1

@sammysaglam vous pouvez accéder à l'état dans l'action-créateur. – WitVault