2017-10-04 15 views
0

J'apprends le redux et les immutables et je fais une application todo.Réagissez Redux L'état immuable n'est pas retourné

lorsque je déclenche l'action add_item je reçois "state.push est pas une fonction"

Si je change cette ligne

const reducer = (state = initialState, action) => { 

à

const reducer = (state = new List(), action) => {

je peux ajouter nouveaux articles, mais les inital ne montrent pas, comment résoudre ce problème?

export const initialState = Map({ 
    items: List (
     Map({ id: 1, content: 'Call mum' }), 
     Map({ id: 2, content: 'Buy cat food' }), 
     Map({ id: 3, content: 'Water the plants' }) 
) 
}); 

const reducer = (state = initialState, action) => { 
    console.log("action.type", action.type); 
    switch (action.type) { 
    case ADD_ITEM: 
     return state.push(Map({ 
     id: nextId++, 
     content: action.content 
     })); 
    default: 
     return state; 
    } 
}; 

Répondre

0

Etat n'est pas une instance de tableau et ne sera donc pas avoir accès à la méthode Array.push(). L'état est un objet.

Premièrement, j'éviterais d'utiliser toute méthode de mutation, par ex. Poussez(), dans votre réducteur lui-même. Il est préférable de garder ceux définis dans vos actions - si vous devez les utiliser.

Je ne vois pas l'utilité de "List" ou "Map" dans cet exemple. Pour être d'esprit littéral:

const initialState = { 
    items: [ 
      {id: 1, content: 'call mum'}, 
      {id: 2, content: 'call dad'}, 
    ], 
} 

Au sein de votre réducteur lui-même, je recommande fortement une méthode immuable comme la propagation de repos objet.

const reducer = (state = initialState, action) => { 
    switch(action.type){ 
    case "ADD_ITEM": 
     return {...state, items: [...state.items, action.newItem]} 
    } 

    ... 
} 

Si vous voulez nourrir votre état initial, vous pouvez définir un autre cas dans votre réducteur comme suit:

switch(action.type){ 
    case "ADD_ITEM": 
     return {...state, items: [...state.items, action.newItem]} 
    case "SET_NEW_LIST": 
     return {...state, items: action.newList} 
    ... 
    } 

Et définir une autre action en conséquence. Plus ou moins, Dan Abramov et d'autres encouragent à garder vos réducteurs aussi simples que possible et à garder la logique dans vos actions autant que possible. Votre incrémentation d'identifiant doit être prise en compte dans votre action ADD_ITEM.

+0

Remerciez vous pour votre réponse mais je voulais utiliser immutablejs comme dans https://www.sitepoint.com/how-to-build-a-todo-app-using-react-redux-and-immutable-js/ que je suis suivre vaguement. Ce qui précède est seulement un extrait de l'application de test que je construis. Sera fonctionnalité supplémentaire pour basculer, supprimer, filtrer l'état. – Adam

0

Il vous suffit de restructurer votre état initial comme ça:

export const initialState = List ([ 
    Map({ id: 1, content: 'Call mum' }), 
    Map({ id: 2, content: 'Buy cat food' }), 
    Map({ id: 3, content: 'Water the plants' }) 
]) 

Si vous souhaitez conserver une structure plus complexe comme Map{ items: List } vous devez factoriser votre réducteur et votre état:

export const initialState = Map({ 
    items: List ([ 
    //   ^don't forget the brackets here 
     Map({ id: 1, content: 'Call mum' }), 
     Map({ id: 2, content: 'Buy cat food' }), 
     Map({ id: 3, content: 'Water the plants' }) 
    ]) 
}); 

const reducer = (state = initialState, action) => { 
    switch (action.type) { 
    case ADD_ITEM: 
     return state.set('items', state.get('items').push(
     Map({ 
      id: nextId++, 
      content: action.content 
     }) 
    )); 
    default: 
     return state; 
    } 
};