1
0

More than 3 years have passed since last update.

【react-native】setStateで値の反映が待てないあなた向け

Posted at

はじめに

setStateをした後にその中の値を使った計算をしたいのに、反映が遅くて使えない・・・
なんて思ったことありませんか。私はありません。ということで対策案を考えました。
まずは事象から見てください。

事象

Mar-05-2020 07-54-36.gif

こちらデモですが、「No1add」「No2add」ボタンを押下することでそれぞれの数字に値を1足す。
その後、合計値にという流れを実装したいのですが、うまくいきません。
合計値がボタンを押す前のNo1とNo2の合計値になってしまいます。

ソースは以下です。

App.js
import React from 'react';
import { StyleSheet, View, Button, Text } from 'react-native';

export default class App extends React.Component {
  state = {
    num1: 0,
    num2: 0,
    sum: 0,
  }
  render() {
    const onPressNo1 = () => {
      this.setState({ num1: this.state.num1 + 1 })
      // 合計点を随時更新する
      calcSum();
    }
    const onPressNo2 = () => {
      this.setState({ num2: this.state.num2 + 1 })
      // 合計点を随時更新する
      calcSum();
    }

    const calcSum = () => {
      this.setState({ sum: this.state.num1 + this.state.num2 })
    }
    return (
      <View style={styles.container}>
        <View style={styles.row}>
          <Button title="No1add" onPress={() => onPressNo1()} />
          <Text style={styles.textStyle}>No1: {this.state.num1}</Text>
        </View>

        <View style={styles.row}>
          <Button title="No2add" onPress={() => onPressNo2()} />
          <Text style={styles.textStyle}>No2: {this.state.num2}</Text>
        </View>

        <Text style={styles.textStyle}>No1 + No2 =  {this.state.sum}</Text>

      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  row: {
    flexDirection: "row",
    alignItems: "center"
  },
  textStyle: {
    fontSize: 20,
  }
});

原因はsetStateで値が反映されるのは画面が再描画されるタイミングのため、合計値の計算のタイミングではまだnum1とnum2の値が更新されていないため。
以下、対策案です。
他にもあれば教えてください。

対策案①:stateに値を直接いれる

これはあまりいけてないですが、パワープレイしたいならこちらが良いでしょう。

App.js
import React from 'react';
import { StyleSheet, View, Button, Text } from 'react-native';

export default class App extends React.Component {
  state = {
    num1: 0,
    num2: 0,
    sum: 0,
  }
  render() {
    var varNum1 = this.state.num1;
    var varNum2 = this.state.num2;
    var varSum = this.state.sum;

    const onPressNo1 = () => {
      varNum1 = this.state.num1 + 1
      this.setState({ num1: varNum1 })
      // 合計点を随時更新する
      calcSum();
    }
    const onPressNo2 = () => {
      varNum2 = this.state.num2 + 1
      this.setState({ num2: varNum2 })
      // 合計点を随時更新する
      calcSum();
    }

    const calcSum = () => {
      varSum = varNum1 + varNum2
      this.setState({ sum: varSum })
    }
    return (
      <View style={styles.container}>
        <View style={styles.row}>
          <Button title="No1add" onPress={() => onPressNo1()} />
          <Text style={styles.textStyle}>No1: {this.state.num1}</Text>
        </View>

        <View style={styles.row}>
          <Button title="No2add" onPress={() => onPressNo2()} />
          <Text style={styles.textStyle}>No2: {this.state.num2}</Text>
        </View>

        <Text style={styles.textStyle}>No1 + No2 =  {this.state.sum}</Text>

      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  row: {
    flexDirection: "row",
    alignItems: "center"
  },
  textStyle: {
    fontSize: 20,
  }
});

変数を新たに用意し、そこに値を入れ即時反映させていくやり方です。
いけてないですが、確実に理想的な実装ができます

対策案②:再描画タイミングで計算しちゃおう

sumをstateでもつことなんてやめましょうw

App.js
import React from 'react';
import { StyleSheet, View, Button, Text } from 'react-native';

export default class App extends React.Component {
  state = {
    num1: 0,
    num2: 0,
  }
  render() {
    const onPressNo1 = () => {
      this.setState({ num1: this.state.num1 + 1 })
    }
    const onPressNo2 = () => {
      this.setState({ num2: this.state.num2 + 1 })
    }

    return (
      <View style={styles.container}>
        <View style={styles.row}>
          <Button title="No1add" onPress={() => onPressNo1()} />
          <Text style={styles.textStyle}>No1: {this.state.num1}</Text>
        </View>

        <View style={styles.row}>
          <Button title="No2add" onPress={() => onPressNo2()} />
          <Text style={styles.textStyle}>No2: {this.state.num2}</Text>
        </View>

        <Text style={styles.textStyle}>No1 + No2 =  {this.state.num1 + this.state.num2}</Text>

      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  row: {
    flexDirection: "row",
    alignItems: "center"
  },
  textStyle: {
    fontSize: 20,
  }
});

まとめ

独学しているとsetStateの正しい使い方これであってるのかな・・・と不安になります。
一旦まとめて見ました。

他に案がある人募集しています。
教えて欲しいです・・・

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0