ホームページ ウェブフロントエンド jsチュートリアル React.setStateを使用する際に注意すべき点は何ですか?

React.setStateを使用する際に注意すべき点は何ですか?

Jun 20, 2018 am 11:17 AM
react setstate

この記事では React.setState を使用する際に注意すべき 3 つの点を中心に紹介します。興味のある方は参考にしてください。前書き

この記事の元のタイトルは「 3 Reasons Why I stop using React.setState 」ですが、私は元の著者が提唱した議論にはあまり興味がありませんが、著者が提起した 3 つの点は無視しやすいものです。 React初心者向けの場なので、ここでは内容の一部のみを紹介し、タイトルをReact.setStateを使う際の注意点3点に変更しました。

Text

React の初心者にとって、setState の使用は非常に複雑です。 React 開発に熟練した人でも、次の例のような React の仕組みによっていくつかのバグが発生する可能性があります:

このドキュメントでは、setState を使用するときにどのような問題に注意する必要があるかについても説明しています:

注:

this.state を直接変更しないでください。後で setState() を呼び出すと、行った変更が置き換えられる可能性があります

。 this.state を不変として扱います。

setState() は this.state をすぐには変更しませんが、すぐに処理される状態遷移を作成します。このメソッドを呼び出した後に this.state にアクセスすると、既存の値が返される場合があります。

setState への呼び出しには同期の保証はなく、パフォーマンス向上のために呼び出しがバッチ化される場合があります。

setState() は、条件付きレンダリング ロジックが shouldComponentUpdate() に実装されていない限り、常に再描画をトリガーします。可変オブジェクトが使用されており、このロジックを shouldComponentUpdate() で実装できない場合は、新しい状態と前の状態に違いがある場合にのみ setState() を呼び出すことで、不必要な再レンダリングを回避できます。

要約すると、setState を使用する場合、注意すべき 3 つの問題があります:

1. setState は非同期です (翻訳者注: 同期は保証されていません)

多くの開発者は、setState が非同期であることに最初は気づきませんでした。 。一部の状態を変更してからそれを直接表示すると、前の状態が表示されます。これは、setState の中で最もエラーが発生しやすい場所です。 setState という単語は非同期に見えないため、何も考えずに使用するとバグが発生する可能性があります。次の例は、この問題をよく示しています:

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")
)
ログイン後にコピー

一見すると、このコードには何も問題がないように見えます。 onSelect メソッドは両方のイベント ハンドラーで呼び出されます。ただし、Select コンポーネントには、前の GIF をうまく表現するバグがあります。 fireOnSelect が呼び出されたとき、setState はまだ作業を完了していないため、onSelect メソッドは常に前の state.selection 値を渡します。 Reactは少なくともsetStateをscheduleStateに変更するか、コールバック関数を必須パラメータにする必要があると思います。

このバグは修正するのが簡単です。最も難しいのは、この問題があることを認識する必要があることです。

2. setState により不要なレンダリングが発生します

setState によって引き起こされる 2 番目の問題は、呼び出しごとに再レンダリングが発生することです。多くの場合、こうした再レンダリングは不要です。 React パフォーマンス ツールで printWasted を使用すると、不必要なレンダリングがいつ発生するかを確認できます。ただし、大まかに言えば、不必要なレンダリングにはいくつかの理由があります:

新しい状態は、実際には前の状態と同じです。この問題は通常、 shouldComponentUpdate を使用して解決できます。この問題を解決するには、純粋なレンダリングまたは他のライブラリを使用することもできます。
  1. 通常、変更された状態はレンダリングに関連しますが、例外もあります。たとえば、一部のデータは特定の状態に基づいて表示されます。
  2. 第三に、一部の州はレンダリングとは関係がありません。一部の状態はイベントやタイマー ID に関連している場合があります。
  3. 3.setState はすべてのコンポーネントの状態を非常に効率的に管理することはできません

上記の最後の点に基づいて、すべてのコンポーネントの状態を setState で保存および更新する必要はありません。複雑なコンポーネントには、管理が必要なさまざまな状態がある場合があります。 setState を使用してこれらの状態を管理すると、不必要な再レンダリングが大量に発生するだけでなく、関連するライフサイクル フックが常に呼び出され、多くの奇妙な問題が発生します。

後日談

元記事では、作者はいくつかの状態を管理するためにMobXというライブラリを推奨していましたが、私はあまり寒くないので紹介しません。ご興味がございましたら、上部のリンクから元記事の紹介文をご覧ください。

上記の 3 つの点を踏まえると、初心者は次の点に注意する必要があると思います:

setState は同期されることが保証されていない

setState は同期されることが保証されていない、同期されることが保証されていない、同期されることが保証されていない同期されること。大事なことは3回言いましょう。非同期とは言えない理由は、setState も同期的に更新される場合があるためです。 この記事を参照してください

setState の直後に変更された値を取得する必要がある場合は、いくつかのオプションがあります:

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中如何实现轨迹回放功能

以上がReact.setStateを使用する際に注意すべき点は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

React と RabbitMQ を使用して信頼性の高いメッセージング アプリを構築する方法 React と RabbitMQ を使用して信頼性の高いメッセージング アプリを構築する方法 Sep 28, 2023 pm 08:24 PM

React と RabbitMQ を使用して信頼性の高いメッセージング アプリケーションを構築する方法 はじめに: 最新のアプリケーションは、リアルタイム更新やデータ同期などの機能を実現するために、信頼性の高いメッセージングをサポートする必要があります。 React はユーザー インターフェイスを構築するための人気のある JavaScript ライブラリであり、RabbitMQ は信頼性の高いメッセージング ミドルウェアです。この記事では、React と RabbitMQ を組み合わせて信頼性の高いメッセージング アプリケーションを構築する方法を紹介し、具体的なコード例を示します。 RabbitMQ の概要:

React Router ユーザーガイド: フロントエンドルーティング制御の実装方法 React Router ユーザーガイド: フロントエンドルーティング制御の実装方法 Sep 29, 2023 pm 05:45 PM

ReactRouter ユーザーガイド: フロントエンドルーティング制御の実装方法 シングルページアプリケーションの人気に伴い、フロントエンドルーティングは無視できない重要な部分になりました。 React エコシステムで最も人気のあるルーティング ライブラリとして、ReactRouter は豊富な機能と使いやすい API を提供し、フロントエンド ルーティングの実装を非常にシンプルかつ柔軟にします。この記事では、ReactRouter の使用方法と具体的なコード例を紹介します。 ReactRouter を最初にインストールするには、次のものが必要です

PHP、Vue、React: 最適なフロントエンド フレームワークを選択するには? PHP、Vue、React: 最適なフロントエンド フレームワークを選択するには? Mar 15, 2024 pm 05:48 PM

PHP、Vue、React: 最適なフロントエンド フレームワークを選択するには?インターネット技術の継続的な発展に伴い、フロントエンド フレームワークは Web 開発において重要な役割を果たしています。 PHP、Vue、React は 3 つの代表的なフロントエンド フレームワークであり、それぞれに独自の特徴と利点があります。使用するフロントエンド フレームワークを選択するとき、開発者はプロジェクトのニーズ、チームのスキル、個人の好みに基づいて情報に基づいた決定を下す必要があります。この記事では、PHP、Vue、React の 3 つのフロントエンド フレームワークの特徴と用途を比較します。

Java フレームワークとフロントエンド React フレームワークの統合 Java フレームワークとフロントエンド React フレームワークの統合 Jun 01, 2024 pm 03:16 PM

Java フレームワークと React フレームワークの統合: 手順: バックエンド Java フレームワークをセットアップします。プロジェクト構造を作成します。ビルドツールを設定します。 React アプリケーションを作成します。 REST API エンドポイントを作成します。通信メカニズムを構成します。実際のケース (SpringBoot+React): Java コード: RESTfulAPI コントローラーを定義します。 React コード: API によって返されたデータを取得して表示します。

React を使用して応答性の高いバックエンド管理システムを開発する方法 React を使用して応答性の高いバックエンド管理システムを開発する方法 Sep 28, 2023 pm 04:55 PM

React を使用して応答性の高いバックエンド管理システムを開発する方法 インターネットの急速な発展に伴い、日々の業務を処理するために効率的で柔軟で管理が容易なバックエンド管理システムを必要とする企業や組織が増えています。現在最も人気のある JavaScript ライブラリの 1 つである React は、ユーザー インターフェイスを構築するための簡潔で効率的かつ保守しやすい方法を提供します。この記事では、React を使用して応答性の高いバックエンド管理システムを開発する方法と、具体的なコード例を紹介します。まず React プロジェクトを作成します

Vue.js vs. React:プロジェクト固有の考慮事項 Vue.js vs. React:プロジェクト固有の考慮事項 Apr 09, 2025 am 12:01 AM

VUE.JSは、中小規模のプロジェクトや迅速な反復に適していますが、Reactは大規模で複雑なアプリケーションに適しています。 1)Vue.jsは使いやすく、チームが不十分な状況やプロジェクトスケールが小さい状況に適しています。 2)Reactにはより豊富なエコシステムがあり、高性能で複雑な機能的ニーズを持つプロジェクトに適しています。

HTMLにおけるReactの役割:ユーザーエクスペリエンスの向上 HTMLにおけるReactの役割:ユーザーエクスペリエンスの向上 Apr 09, 2025 am 12:11 AM

ReactはJSXとHTMLを組み合わせてユーザーエクスペリエンスを向上させます。 1)JSXはHTMLを埋め込み、開発をより直感的にします。 2)仮想DOMメカニズムは、パフォーマンスを最適化し、DOM操作を削減します。 3)保守性を向上させるコンポーネントベースの管理UI。 4)国家管理とイベント処理は、インタラクティブ性を高めます。

反応にはどのようなクロージャがありますか? 反応にはどのようなクロージャがありますか? Oct 27, 2023 pm 03:11 PM

React には、イベント処理関数、useEffect や useCallback、上位コンポーネントなどのクロージャがあります。詳細な紹介: 1. イベント処理関数のクロージャ: React では、コンポーネント内でイベント処理関数を定義すると、関数はクロージャを形成し、コンポーネントのスコープ内のステータスとプロパティにアクセスできます。このようにして、コンポーネントの状態とプロパティをイベント処理関数で使用して対話型ロジックを実装できます; 2. useEffect や useCallback のクロージャなど。

See all articles