Heim >Web-Frontend >js-Tutorial >Was sollten Sie bei der Verwendung von React.setState beachten?

Was sollten Sie bei der Verwendung von React.setState beachten?

亚连
亚连Original
2018-06-20 11:17:551759Durchsuche

In diesem Artikel werden hauptsächlich drei Punkte vorgestellt, die bei der Verwendung von React.setState beachtet werden müssen. Es werden drei Punkte genannt, die für React-Neulinge leicht zu ignorieren sind. Es hat einen gewissen Referenzwert >

Vorwort

Der Originaltitel dieses Artikels lautet 3 Gründe, warum ich React.setState nicht mehr verwendet habe, aber die Argumente des ursprünglichen Autors interessieren mich nicht sehr. Aber die drei vom Autor angesprochenen Punkte sind für React-Neulinge leicht zu ignorieren, daher werde ich hier nur einen Teil des Inhalts erwähnen und den Titel in drei Punkte ändern, die bei der Verwendung von React.setState beachtet werden müssen.

Text

Für React-Neulinge ist die Verwendung von setState eine sehr komplizierte Sache. Selbst wenn Sie ein erfahrener React-Entwickler sind, ist es sehr wahrscheinlich, dass aufgrund einiger Mechanismen von React einige Fehler auftreten, wie zum Beispiel das folgende Beispiel:

Das Dokument erklärt auch bei der Verwendung von setState Was sollten Sie dabei beachten:

Hinweis:

Ändern Sie this.state niemals direkt, da ein späterer Aufruf von setState() das ersetzen kann Änderungen, die Sie vorgenommen haben

Änderung. Behandeln Sie this.state als unveränderlich.

setState() ändert this.state nicht sofort, sondern erstellt einen Zustandsübergang, der bald verarbeitet wird. Der Zugriff auf this.state nach dem Aufruf dieser Methode gibt möglicherweise den vorhandenen Wert zurück.

Aufrufe an setState haben keine Synchronisierungsgarantien und Aufrufe können zur Leistungssteigerung gestapelt werden.

setState() löst immer eine Neuzeichnung aus, es sei denn, die bedingte Rendering-Logik ist in ShouldComponentUpdate() implementiert. Wenn veränderliche Objekte verwendet werden und diese Logik nicht in ShouldComponentUpdate() implementiert werden kann, kann der Aufruf von setState() nur dann, wenn ein Unterschied zwischen dem neuen Zustand und dem vorherigen Zustand besteht, unnötiges erneutes Rendern vermeiden.

Zusammenfassend lässt sich sagen, dass bei der Verwendung von setState drei Probleme zu beachten sind:

1. setState ist asynchron (Anmerkung des Übersetzers: Synchronisierung ist nicht garantiert)

Vielen Entwicklern ist zunächst nicht aufgefallen, dass setState asynchron ist. Wenn Sie einen Status ändern und ihn dann direkt anzeigen, wird der vorherige Status angezeigt. Dies ist die fehleranfälligste Stelle in setState. Das Wort setState sieht nicht asynchron aus und kann daher Fehler verursachen, wenn Sie es unüberlegt verwenden. Das folgende Beispiel veranschaulicht dieses Problem gut:

class Select extends React.Component {
 constructor(props, context) {
  super(props, context)
  this.state = {
   selection: props.values[0]
  };
 }
 
 render() {
  return (
   <ul onKeyDown={this.onKeyDown} tabIndex={0}>
    {this.props.values.map(value =>
     <li
      className={value === this.state.selection ? &#39;selected&#39; : &#39;&#39;}
      key={value}
      onClick={() => this.onSelect(value)}
     >
      {value}
     </li> 
    )} 
   </ul>
  )
 }
 
 onSelect(value) {
  this.setState({
   selection: value
  })
  this.fireOnSelect()
 }

 onKeyDown = (e) => {
  const {values} = this.props
  const idx = values.indexOf(this.state.selection)
  if (e.keyCode === 38 && idx > 0) { /* up */
   this.setState({
    selection: values[idx - 1]
   })
  } else if (e.keyCode === 40 && idx < values.length -1) { /* down */
   this.setState({
    selection: values[idx + 1]
   }) 
  }
  this.fireOnSelect()
 }
  
 fireOnSelect() {
  if (typeof this.props.onSelect === "function")
   this.props.onSelect(this.state.selection) /* not what you expected..*/
 }
}

ReactDOM.render(
 <Select 
  values={["State.", "Should.", "Be.", "Synchronous."]} 
  onSelect={value => console.log(value)}
 />,
 document.getElementById("app")
)

Auf den ersten Blick scheint an diesem Code nichts auszusetzen zu sein. Die Methode onSelect wird in beiden Event-Handlern aufgerufen. Es gibt jedoch einen Fehler in dieser Select-Komponente, der das vorherige GIF gut darstellt. Die onSelect-Methode übergibt immer den vorherigen state.selection-Wert, da setState beim Aufruf von fireOnSelect seine Arbeit noch nicht abgeschlossen hat. Ich denke, React sollte zumindest setState in ScheduleState ändern oder die Callback-Funktion zu einem erforderlichen Parameter machen.

Dieser Fehler ist leicht zu beheben. Das Schwierigste ist, dass Sie wissen müssen, dass es dieses Problem gibt.

2. setState führt zu unnötigem Rendering

Das zweite durch setState verursachte Problem ist: Jeder Aufruf führt zu einem erneuten Rendering. Oft sind diese erneuten Renderings unnötig. Sie können printWasted in den React-Leistungstools verwenden, um zu sehen, wann unnötiges Rendering auftritt. Grob gesagt gibt es jedoch mehrere Gründe für unnötiges Rendern:

  1. Der neue Zustand ist tatsächlich derselbe wie der vorherige. Dieses Problem kann normalerweise mit ShouldComponentUpdate gelöst werden. Sie können dieses Problem auch mit Pure Render oder anderen Bibliotheken lösen.

  2. Normalerweise hängt der geänderte Status mit dem Rendern zusammen, es gibt jedoch Ausnahmen. Beispielsweise werden einige Daten basierend auf bestimmten Zuständen angezeigt.

  3. Drittens haben einige Zustände nichts mit dem Rendern zu tun. Einige Zustände können mit Ereignissen und Timer-IDs zusammenhängen.

3.setState kann nicht alle Komponentenzustände effektiv verwalten

Basierend auf dem letzten Punkt oben sollten nicht alle Komponentenzustände mit SetState verwendet werden speichern und aktualisieren. Komplexe Komponenten können unterschiedliche Zustände aufweisen, die verwaltet werden müssen. Die Verwendung von setState zum Verwalten dieser Zustände führt nicht nur zu vielen unnötigen erneuten Renderings, sondern führt auch dazu, dass zugehörige Lebenszyklus-Hooks ständig aufgerufen werden, was zu vielen seltsamen Problemen führt.

Nachwort

Im Originalartikel empfahl der Autor eine Bibliothek namens MobX, um einige Zustände zu verwalten, deshalb werde ich sie nicht vorstellen. Wenn Sie interessiert sind, können Sie die Einleitung im Originalartikel über den Link oben lesen.

Basierend auf den drei oben genannten Punkten denke ich, dass Neulinge Folgendes beachten sollten:

setState ist nicht garantiert synchronisiert.

setState ist nicht garantiert synchronisiert , es ist nicht garantiert. Die Synchronisierung ist nicht garantiert. Sagen Sie wichtige Dinge dreimal. Der Grund, warum es nicht als asynchron bezeichnet wird, liegt darin, dass setState in einigen Fällen auch synchron aktualisiert wird. Sie können auf diesen Artikel verweisen

Wenn Sie den geänderten Wert direkt nach setState abrufen müssen, gibt es mehrere Möglichkeiten:

Übergeben Sie die entsprechenden Parameter und erhalten Sie ihn nicht über this.state

针对于之前的例子,完全可以在调用 fireOnSelect 的时候,传入需要的值。而不是在方法中在通过 this.state 来获取

使用回调函数

setState 方法接收一个 function 作为回调函数。这个回掉函数会在 setState 完成以后直接调用,这样就可以获取最新的 state 。对于之前的例子,就可以这样:

this.setState({
 selection: value
}, this.fireOnSelect)

使用setTimeout

在 setState 使用 setTimeout 来让 setState 先完成以后再执行里面内容。这样子:

this.setState({
 selection: value
});
setTimeout(this.fireOnSelect, 0);

直接输出,回调函数, setTimeout 对比

componentDidMount(){
  this.setState({val: this.state.val + 1}, ()=>{
   console.log("In callback " + this.state.val);
  });

  console.log("Direct call " + this.state.val);  
  setTimeout(()=>{
   console.log("begin of setTimeout" + this.state.val);
    this.setState({val: this.state.val + 1}, ()=>{
     console.log("setTimeout setState callback " + this.state.val);
    });

   setTimeout(()=>{
    console.log("setTimeout of settimeout " + this.state.val);
   }, 0);

   console.log("end of setTimeout " + this.state.val);
  }, 0);
 }

如果val默认为0, 输入的结果是:

Direct call 0
In callback 1
begin of setTimeout 1
setTimeout setState callback 2
end of setTimeout 2
setTimeout of settimeout 2

和渲染无关的状态尽量不要放在 state 中来管理

通常 state 中只来管理和渲染有关的状态 ,从而保证 setState 改变的状态都是和渲染有关的状态。这样子就可以避免不必要的重复渲染。其他和渲染无关的状态,可以直接以属性的形式保存在组件中,在需要的时候调用和改变,不会造成渲染。

避免不必要的修改,当 state 的值没有发生改变的时候,尽量不要使用 setState 。虽然 shouldComponentUpdate 和 PureComponent 可以避免不必要的重复渲染,但是还是增加了一层 shallowEqual 的调用,造成多余的浪费。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在vue中使用axios实现文件上传

使用gulp如何创建完整的项目流程

在js中如何实现将数组添加到对象中

在jQuery中如何实现动态控制页面元素

在canvas中如何实现轨迹回放功能

Das obige ist der detaillierte Inhalt vonWas sollten Sie bei der Verwendung von React.setState beachten?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn