[解決済み] なぜ、コンポーネントの状態を直接変更できないのですか?
質問
Reactのチュートリアルやドキュメントの警告は
で警告しています。
で警告しているように、状態は直接変更されるべきではなく、すべては
setState
.
なぜ、直接状態を変更してから (同じ関数内で)
this.setState({})
をトリガーするだけでは
render
.
例: 以下のコードは問題なく動作するようです。
const React = require('react');
const App = React.createClass({
getInitialState: function() {
return {
some: {
rather: {
deeply: {
embedded: {
stuff: 1,
},
},
},
},
},
};
updateCounter: function () {
this.state.some.rather.deeply.embedded.stuff++;
this.setState({}); // just to trigger the render ...
},
render: function() {
return (
<div>
Counter value: {this.state.some.rather.deeply.embedded.stuff}
<br></br>
<button onClick={this.updateCounter}>Increment</button>
</div>
);
},
});
export default App;
私は規則に従うことに賛成ですが、ReactJSが実際にどのように動作し、何が間違っているのか、または上記のコードで最適ではないのかについて、さらに理解を深めたいと思います。
の下にある注意書きは
this.setState
ドキュメント
は、基本的に二つのゴチャゴチャを識別します。
-
状態を直接変異させ、その後に
this.setState
を呼び出すと、行った変異を置き換える(上書きする?)かもしれません。上記のコードでこれがどのように起こるかはわかりません。 -
は、その
setState
は変異する可能性があるthis.state
を非同期/遅延方式で効果的に変異させることができます。this.state
を呼び出した直後にthis.setState
を呼んだ直後では、最終的な変異した状態へのアクセスは保証されません。それはわかったのですが、もしthis.setState
が更新関数の最後の呼び出しであれば問題ありません。
どのように解決するのですか?
のReactドキュメントは
setState
はこのように言っています。
NEVER 変異させる
this.state
を呼び出すように、直接setState()
を呼び出すと、行った変異が置き換わる可能性があるからです。扱うthis.state
をあたかも不変であるかのように扱います。
setState()
はすぐに変異しないthis.state
を変異させるのではなく、保留中の状態遷移を生成します。アクセスするthis.state
にアクセスすると、既存の値が返される可能性があります。への呼び出しの同期動作は保証されていません。
setState
の呼び出しは同期動作が保証されておらず、性能向上のためにバッチ処理されることがあります。
setState()
に条件付きレンダリングロジックが実装されていない限り、常に再レンダリングのトリガーとなります。shouldComponentUpdate()
. ミュータブルオブジェクトが使われていて、そのロジックがshouldComponentUpdate()
に実装できない場合はsetState()
を呼び出すことで、不必要な再レンダリングを避けることができます。
基本的に、もしあなたが
this.state
を直接修正すると、その修正が上書きされるかもしれない状況を作り出してしまいます。
拡張された質問1)と2)に関連します。
setState()
は即時性がない。
への直接的な変更を含まないかもしれない、それが起こっていると考えるものに基づいて、状態遷移を待ちます。
this.state
. すぐに適用されるのではなく、キューに入れられるので、その間に何かが変更され、直接の変更が上書きされることは十分にあり得ます。
もし何もなければ、直接の変更ではなく
this.state
を直接修正しないことは、良い習慣と見なすことができます。あなたのコードが、これらの上書きやその他の問題が起こらないような方法で React と相互作用することを個人的に知っているかもしれませんが、他の開発者や将来の更新が突然奇妙なまたは微妙な問題に気付くことができる状況を作り出しています。
関連
-
[解決済み] React JSでは、状態を直接変異させない、setState() react/no-direct-mutation-stateを使用する。
-
[解決済み] 配列からオブジェクトを生成する
-
[解決済み] 文字列がhtmlであるかどうかをチェックする
-
[解決済み] jQueryの$という記号の意味は何ですか?
-
[解決済み] react-routerのハッシュフラグメントからクエリパラメータを取得する
-
[解決済み] jQueryで入力ファイルが空かどうかをチェックする方法
-
[解決済み] モデルフェッチ時に1をtrueに、0をfalseに変換する方法
-
[解決済み] jQueryのバージョン1、バージョン2、バージョン3の違いは何ですか?[クローズド]
-
[解決済み] JavaScriptデータフォーマット/プリティプリンタ
-
[解決済み] JavaScriptでDIVを表示・非表示にするには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] JavaScriptで次の要素/前の要素を取得しますか?
-
[解決済み] JavaScriptのtoString()関数をオーバーライドして、デバッグ用に意味のある出力を提供することは可能でしょうか?
-
[解決済み] 無効になっている入力フィールドの値を送信する
-
[解決済み] jQueryの$という記号の意味は何ですか?
-
[解決済み] JavaScript のオブジェクトの配列を比較し、最小値/最大値を取得する
-
[解決済み] AJAX Mailchimp サインアップフォームの統合
-
[解決済み] Promise : then vs then + catch [重複].
-
[解決済み] <ng-content>が空かどうかを確認する方法は?(これまでのAngular 2+で)
-
[解決済み] Fetch: ステータスがOKでない場合、プロミスを拒否し、エラーをキャッチするか?
-
[解決済み] JavaScriptでDIVを表示・非表示にするには?