disconoscimento
Lo stato nidificato in React ha un design errato
Leggi questa risposta eccellente .
Ragionamento dietro questa risposta:
SetState di React è solo una comodità integrata, ma presto ti rendi conto che ha i suoi limiti. L'uso di proprietà personalizzate e l'uso intelligente di forceUpdate ti offrono molto di più. per esempio:
class MyClass extends React.Component {
myState = someObject
inputValue = 42
...
MobX, ad esempio, i fossi dichiarano completamente e usano proprietà osservabili personalizzate.
Usa gli osservabili anziché lo stato nei componenti di React.
Esiste un altro modo più breve per aggiornare qualsiasi proprietà nidificata.
this.setState(state => {
state.nested.flag = false
state.another.deep.prop = true
return state
})
Su una riga
this.setState(state => (state.nested.flag = false, state))
nota: questo qui è Operatore virgola ~ MDN , vederlo in azione qui (Sandbox) .
È simile a (sebbene questo non cambi il riferimento di stato)
this.state.nested.flag = false
this.forceUpdate()
Per la sottile differenza in questo contesto tra forceUpdate
e setState
vedere l'esempio collegato.
Naturalmente questo sta abusando di alcuni principi fondamentali, come state
dovrebbe essere di sola lettura, ma poiché scarti immediatamente il vecchio stato e lo sostituisci con uno nuovo, è completamente ok.
avvertimento
Anche se il componente che contiene lo stato si aggiornerà e eseguirà nuovamente il rendering ( tranne questo gotcha ) , gli oggetti di scena non si propagheranno ai bambini (vedere il commento di Spymaster di seguito) . Usa questa tecnica solo se sai cosa stai facendo.
Ad esempio, puoi passare un puntello piatto modificato che viene aggiornato e passato facilmente.
render(
//some complex render with your nested state
<ChildComponent complexNestedProp={this.state.nested} pleaseRerender={Math.random()}/>
)
Ora, anche se il riferimento per complexNestedProp non è cambiato ( shouldComponentUpdate )
this.props.complexNestedProp === nextProps.complexNestedProp
il componente eseguirà nuovamente il rendering ogni volta che il componente padre si aggiorna, come nel caso della chiamata this.setState
o this.forceUpdate
nel padre.
Effetti della mutazione dello stato
Uso stato annidato e mutando direttamente lo stato è pericoloso perché diversi oggetti potrebbero tenere (intenzionalmente o meno) diversi (vecchi) riferimenti alla condizione e potrebbero non necessariamente sapere quando dell'aggiornamento (ad esempio quando si utilizza PureComponent
o se shouldComponentUpdate
viene implementato per ritorno false
) OR sono destinato a visualizzare vecchi dati come nell'esempio seguente.
Immagina una linea temporale che dovrebbe rendere i dati storici, la mutazione dei dati sotto la mano comporterà un comportamento imprevisto in quanto cambierà anche gli elementi precedenti.
Comunque qui puoi vedere che Nested PureChildClass
non è stato reso di nuovo a causa della mancata propagazione degli oggetti di scena.