状態を更新しないsetStateを反応させる


99

だから私はこれを持っています:

let total = newDealersDeckTotal.reduce(function(a, b) {
  return a + b;
},
0);

console.log(total, 'tittal'); //outputs correct total
setTimeout(() => {
  this.setState({dealersOverallTotal: total});
}, 10);

console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1'); //outputs incorrect total

newDealersDeckTotalは単なる数値の配列です。[1, 5, 9]たとえばthis.state.dealersOverallTotal、正しい合計は表示されませんが、表示されますtotalか?これで問題が解決するかどうかを確認するために、タイムアウト遅延を設定しました。明らかなことはありますか、それとももっとコードを投稿する必要がありますか?



@Assan乾杯!!
ワーム

回答に記載されていることに加えて、を呼び出すに、状態の値を明示的にログに記録していますsetState
Felix Kling 2017年

1
@FelixKlingいいえ、設定にthis.stateと呼んでいます。以前に変数をログに記録しています。番号?
ワーム

タイムアウトのためsetState、状態をログに記録した後、実際に実行されます。デバッグで行うつもりだったのは、console.logパーツをタイムアウトの内側とsetState外側に配置することだったと思います。
ファビアンシュルツ2017年

回答:


192

setState()通常は非同期です。つまりconsole.log、状態を設定した時点では、まだ更新されていません。setState()メソッドのコールバックにログを入れてみてください。状態変更が完了した後に実行されます。

this.setState({ dealersOverallTotal: total }, () => {
  console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1');
}); 

2
それに加えて、OPは、を呼び出すに状態値を明示的にログに記録しますsetState
Felix Kling 2017年

これは私にとっても機能します。過去にこれを使用しました: `this.setState({someVar:newValue}、function(){console.log(" force update}); 'しかし、何らかの理由でそれは心配していませんでした。これ以上、上記のようにコードを更新すると、機能します。理由は何ですか?
Jozcar 2017

1
@Jozcarも機能するはずですが、構文が正しくありませんでした(括弧がありません):this.setState({someVar: newValue},function(){ console.log("force update") });
Fabian Schultz

imgur.com/Ku0OjTlこの問題を取り除くために何をすべきか教えてください。
ジョンシー2018

1
私はそれが非同期呼び出しであるという事実を完全に忘れていて、これを除いてすべての可能なコード変更を行いました、そしてここであなたは私の脳が燃え尽きるのを防ぎました。ありがとう
ヘムM20年

17

setStateは非同期です。コールバックメソッドを使用して、更新された状態を取得できます。

changeHandler(event) {
    this.setState({ yourName: event.target.value }, () => 
    console.log(this.state.yourName));
 }

12

async / awaitの使用

async changeHandler(event) {
    await this.setState({ yourName: event.target.value });
    console.log(this.state.yourName);
}

8

setState()操作は、非同期ので、あなたがconsole.log()前に実行されるsetState()突然変異した値を、したがって、あなたは結果を参照してください。

これを解決するにはsetState()、次のようなのコールバック関数に値を記録します。

setTimeout(() => {
    this.setState({dealersOverallTotal: total},
    function(){
       console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1');
    });
}, 10)

JavaScriptは常に同期しています。
SantoshSingh19年

1
@santoshsinghあなたには誤解があります。API呼び出し、タイムアウトはすべて非同期で発生します。
ShubhamKhatri19年

あなたが上で述べたように、javascriptは非同期です---それは正しくありません。その主に同期であり、場合によっては非同期です。 stackoverflow.com/questions/2035645/...
Santosh Singhの

@santoshsingh。ああ、それは私の側の間違いでした。文を正しく形成しなかった
ShubhamKhatri19年

コールバックを非常に巧妙に使用して、次の呼び出しの前に状態が更新されるようにします。
user12042 1419年

7

フックの場合は、フックを使用する必要がありますuseEffect

const [fruit, setFruit] = useState('');

setFruit('Apple');

useEffect(() => {
  console.log('Fruit', fruit);
}, [fruit])

すばらしいです。useEffectで動作します。しかし、なぜそれが必要なのですか?
alex3 5120

useEffectすべての再レンダリングで実行され、配列に渡されたアイテムが状態変数である場合、変更されます。したがって、フルーツが変更されてコンポーネントが再レンダリングされると、そのuseEffectが実行されます。
SirajAlam20年

useEffectの外部でsetFruitとconsole.logフルーツを実行しましたが、変更されません。:/
alex3 5120

4

setstateはreactで非同期であるため、コンソールで更新された状態を確認するには、以下に示すようにコールバックを使用します(コールバック関数はsetstateの更新後に実行されます)

ここに画像の説明を入力してください

以下の方法は「推奨されません」ですが、理解のために、状態を直接変更すると、次の行で更新された状態を確認できます。繰り返しますが、これは「お勧めしません」です

ここに画像の説明を入力してください


あなたが直接変数を設定する必要があり、これがそれですありがとう
notacorn


1

私はいくつかの複雑なコードで同じ状況にあり、既存の提案からは何もうまくいきませんでした。

私の問題はsetState、コンポーネントの1つによって発行されたコールバック関数から発生していたことでした。そして、私の疑わしいのは、呼び出しが同期的に発生していたため、setState状態をまったく設定できなかったことです。

簡単に言えば、私はこのようなものを持っています:

render() {
    <Control
        ref={_ => this.control = _}
        onChange={this.handleChange}
        onUpdated={this.handleUpdate} />
}

handleChange() {
    this.control.doUpdate();
}

handleUpdate() {
    this.setState({...});
}

私はそれを置くことだった「修正」しなければならなかった道doUpdate()setTimeout:次のように

handleChange() {
    setTimeout(() => { this.control.doUpdate(); }, 10);
}

理想的ではありませんが、そうでなければ重要なリファクタリングになります。


これで問題は解決しましたが、代わりにsetState()をsetTimeout()内に配置しました。ありがとうございました!
thargenediad

0

反応状態を複数回設定すると問題が発生しました(常にデフォルト状態を使用していました)。このreact / githubの問題に続いて私のために働いた

const [state, setState] = useState({
  foo: "abc",
  bar: 123
});

// Do this!
setState(prevState => {
  return {
    ...prevState,
    foo: "def"
  };
});
setState(prevState => {
  return {
    ...prevState,
    bar: 456
  };
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.