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 forceUpdatee setStatevedere l'esempio collegato.
Naturalmente questo sta abusando di alcuni principi fondamentali, come statedovrebbe 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.setStateo this.forceUpdatenel 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 PureComponento se shouldComponentUpdateviene 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 PureChildClassnon è stato reso di nuovo a causa della mancata propagazione degli oggetti di scena.