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

#はじめに

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

#事象
![Mar-05-2020 07-54-36.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541882/c45f391d-5e0f-34e7-083e-02f2279c73d3.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の正しい使い方これであってるのかな・・・と不安になります。
一旦まとめて見ました。

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