2017-07-21 2 views
0

Was genau meinen sie? Wenn ich it richtig verstehe, kann ich nicht verwenden, wenn this.state neuen Zustand zu berechnen, es sei denn ich eine Funktion als ersten Parameter setState() passieren:Statusaktualisierungen können asynchron sein

// Wrong 
this.setState({a: f(this.state)}); 

// Correct 
this.setState(prevState => {return {a: f(prevState)}}); 

Aber ich this.state was zu entscheiden, verwenden können, um zu tun:

if (this.state.a) 
    this.setState({b: 2}); 

Was ist mit Requisiten?

// Correct or wrong? 
this.setState({name: f(this.props)}); 

Und angeblich kann ich nicht erwarten, dass this.state nach this.setState Aufruf zu ändern:

this.setState({a: 1}); 
console.log(this.state.a); // not necessarily 1 

Dann sage ich eine Liste von Benutzern haben. Und ein wählen, wo ich aktuelle Benutzer machen kann:

export default class App extends React.Component { 
    ... 

    setCurrentUserOption(option) { 
     this.setState({currentUserOption: option}); 
     if (option) 
      ls('currentUserOption', option); 
     else 
      ls.remove('currentUserOption'); 
    } 

    handleAddUser(user) { 
     const nUsers = this.state.users.length; 
     this.setState(prevState => { 
      return {users: prevState.users.concat(user)}; 
     },() => { 
      // here we might expect any number of users 
      // but if first user was added, deleted and added again 
      // two callbacks will be called and setCurrentUserOption 
      // will eventually get passed a correct value 

      // make first user added current 
      if (! nUsers) 
       this.setCurrentUserOption(this.userToOption(user)); 
     }); 
    } 

    handleChangeUser(user) { 
     this.setState(prevState => { 
      return {users: prevState.users.map(u => u.id == user.id ? user : u)}; 
     },() => { 
      // again, we might expect any state here 
      // but a sequence of callback will do the right thing 
      // in the end 

      // update value if current user was changed 
      if (_.get(this.state, 'currentUserOption.value') == user.id) 
       this.setCurrentUserOption(this.userToOption(user)); 
     }); 
    } 

    handleDeleteUser(id) { 
     this.setState(prevState => { 
      return {users: _.reject(prevState.users, {id})}; 
     },() => { 
      // same here 

      // choose first user if current one was deleted 
      if (_.get(this.state, 'currentUserOption.value') == id) 
       this.setCurrentUserOption(this.userToOption(this.state.users[0])); 
     }); 
    } 

    ... 
} 

Haben alle Rückrufe in Folge für Charge von Änderungen in dem Zustand ausgeführt werden, wurde angewandt?

Auf den zweiten Gedanken, setCurrentUserOption ist im Grunde wie setState. Änderungen werden in this.state eingereiht. Selbst wenn Callbacks nacheinander aufgerufen werden, kann ich nicht darauf vertrauen, dass this.state durch vorherigen Callback geändert wird, kann ich? So ist es nicht am besten sein könnte setCurrentUserOption Methode zu extrahieren:

handleAddUser(user) { 
    const nUsers = this.state.users.length; 
    this.setState(prevState => { 
     let state = {users: prevState.users.concat(user)}; 
     if (! nUsers) { 
      state['currentUserOption'] = this.userToOption(user); 
      this.saveCurrentUserOption(state['currentUserOption']); 
     } 
     return state; 
    }); 
} 

saveCurrentUserOption(option) { 
    if (option) 
     ls('currentUserOption', option); 
    else 
     ls.remove('currentUserOption'); 
} 

So kann ich von Änderungen kostenlos currentUserOption erhalten Schlange stehen.

+0

Nur doppelte Überprüfung verwenden Sie alle staatlichen Management-Frameworks wie Redux oder Flussmittel? Antwort könnte je nach – aug

+0

ich werde gehen. Aber jetzt möchte ich es ohne Redux machen. –

Antwort

3

Sie haben nicht wirklich eine sehr spezifische Frage gestellt. "Was bedeutet das?" Ist nicht sehr viel weiter zu machen. Aber im Allgemeinen scheinen Sie die Grundlagen zu verstehen.

setState() Es gibt zwei Möglichkeiten, setState() aufzurufen: entweder durch Übergabe eines Objekts an den neuen Zustand oder durch Übergabe einer Funktion, die ein Objekt zurückgibt, das auf ähnliche Weise wie beim ersten Weg zusammengeführt wird.

Also entweder Sie dies tun:

// Method #1 
this.setState({foo: this.state.foo + 1}, this.someCallback); 

Oder diese:

// Method #2 
this.setState((prevState) => {return {foo: prevState.foo + 1}}, this.someCallback); 

Der wesentliche Unterschied besteht darin, dass mit der Methode # 1, wird foo von 1 basierend auf erhöht bekommen, was Staat es war zu der Zeit, die Sie setState() anrufen, während in Methode # 2 foo wird um 1 basierend auf inkrementiert werden, was auch immer der vorherige Zustand in dem Moment war, dass der Pfeil fu nction läuft. Wenn Sie also mehrere setState() Aufrufe haben, die zur "gleichen" Zeit vor der eigentlichen Statusaktualisierung passieren, können sie bei Methode # 1 einen Konflikt verursachen und/oder auf einem veralteten Zustand basieren, während sie bei Methode # 2 garantiert die höchste Stufe haben -zu-Datum-Zustand, weil sie synchron nacheinander in der Zustandsaktualisierungsphase aktualisiert werden.Hier

ist ein anschauliches Beispiel:


Method #1 JSBIN Example

// Method #1 
class App extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = {n: 0}; 
    this.increment.bind(this); 
    } 
    componentDidMount() { 
    this.increment(); 
    this.increment(); 
    this.increment(); 
    } 
    increment() { 
    this.setState({n: this.state.n + 1},() => {console.log(this.state.n)}); 
    } 
    render() { 
    return (  
     <h1>{this.state.n}</h1>  
    ); 
    } 
} 

React.render(
    <App />, 
    document.getElementById('react_example') 
); 

In der oben: Sie dies in der Konsole sehen würde:

> 1 
> 1 
> 1 

und dem Endwert von this.state.n wäre 1. Alle setState() Anrufe wurden in die Warteschlange eingereiht, wenn der Wert n0 war, so dass sie alle einfach auf 0 + 1 gesetzt sind.


Method #2 JSBIN Example

// Method #2 
class App extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = {n: 0}; 
    this.increment.bind(this); 
    } 
    componentDidMount() { 
    this.increment(); 
    this.increment(); 
    this.increment(); 
    } 
    increment() { 
    this.setState((prevState) => {return {n: prevState.n + 1}},() => {console.log(this.state.n)}); 
    } 
    render() { 
    return (  
     <h1>{this.state.n}</h1>  
    ); 
    } 
} 

React.render(
    <App />, 
    document.getElementById('react_example') 
); 

In der obigen, würden Sie dies in der Konsole sehen:

> 3 
> 3 
> 3 

Und der letzte Wert von n würde 3 sein. Wie bei Methode Nr. 1 wurden alle Anrufe setState() zur gleichen Zeit in die Warteschlange gestellt. Da sie jedoch eine Funktion zur synchronen Aktualisierung in der Reihenfolge verwenden, in der der aktuellste Status verwendet wird - einschließlich Statusänderungen, die durch gleichzeitige Statusaktualisierungen vorgenommen werden - erhöhen sie den Wert n dreimal wie erwartet.


Nun, warum nicht zeigen console.log()3 dreimal für Methode # 2, statt 1, 2, 3? Die Antwort ist, dass setState() Callbacks alle zusammen am Ende der Statusaktualisierungsphase in React geschehen, nicht unmittelbar nach der jeweiligen Statusaktualisierung. Insofern sind die Methoden # 1 und # 2 identisch.

Verwandte Themen