2016-02-25 10 views
30

Ho un problema in cui il re-rendering dello stato causa problemi ui ed è stato suggerito di aggiornare solo il valore specifico all'interno del mio riduttore per ridurre la quantità di re-rendering su una pagina.Come aggiornare un singolo valore all'interno di un elemento specifico dell'array in redux

questo è esempio di mio stato

{ 
name: "some name", 
subtitle: "some subtitle", 
contents: [ 
    {title: "some title", text: "some text"}, 
    {title: "some other title", text: "some other text"} 
] 
} 

e sto aggiornando in questo modo

case 'SOME_ACTION': 
    return { ...state, contents: action.payload } 

dove action.payload è un intero array contenente nuovi valori. Ma ora ho in realtà solo bisogno di aggiornare il testo del secondo elemento contenuto dell'array, e qualcosa come questo non funziona

case 'SOME_ACTION': 
    return { ...state, contents[1].text: action.payload } 

dove action.payload è ora un testo che mi serve per l'aggiornamento.

risposta

14

è possibile utilizzare il React Immutability helpers

import update from 'react-addons-update'; 

// ...  

case 'SOME_ACTION': 
    return update(state, { 
    contents: { 
     1: { 
     text: {$set: action.payload} 
     } 
    } 
    }); 

Anche se posso immaginare che si sarebbe probabilmente fare qualcosa di più simile a questo?

case 'SOME_ACTION': 
    return update(state, { 
    contents: { 
     [action.id]: { 
     text: {$set: action.payload} 
     } 
    } 
    }); 
+0

in effetti, devo includere questi helper per reagire in qualche modo all'interno del mio riduttore? – Ilja

+0

'importazione aggiornamento da 'react-addons-update';' – Clarkie

+3

Sebbene il pacchetto sia stato spostato in 'kolodny/immutability-helper', ora è' yarn add immutability-helper' e 'import update da 'immutability-helper'; ' – SacWebDeveloper

4

Non devi fare tutto in una sola riga:

case 'SOME_ACTION': 
    const newState = { ...state }; 
    newState.contents = 
    [ 
     newState.contents[0], 
     {title: newState.contnets[1].title, text: action.payload} 
    ]; 
    return newState 
+0

Hai ragione, ho fatto una soluzione rapida. btw, la lunghezza dell'array è fissa? e anche l'indice che desideri modificare è fisso? L'approccio attuale è possibile solo con array piccoli e con indice fisso. – Kujira

+0

avvolgere il corpo del caso in {}, poiché const è a blocchi. –

51

È possibile utilizzare map. Ecco un esempio di implementazione:

case 'SOME_ACTION': 
    return { 
     ...state, 
     contents: state.contents.map(
      (content, i) => i === 1 ? {...content, text: action.payload} 
            : content 
     ) 
    } 
+0

è così che sto facendo anche io, non sono sicuro che sia un buon approccio o meno dato che la mappa restituirà un nuovo array. qualche idea? – Ventura

+0

@Ventura Sì, è buono perché sta creando un nuovo riferimento per l'array e un nuovo oggetto semplice per quello destinato ad essere aggiornato (e solo quello), che è esattamente quello che vuoi – ivcandela

+0

Penso che questo sia l'apice migliore –

Problemi correlati