#はじめに
setStateをした後にその中の値を使った計算をしたいのに、反映が遅くて使えない・・・
なんて思ったことありませんか。私はありません。ということで対策案を考えました。
まずは事象から見てください。
こちらデモですが、「No1add」「No2add」ボタンを押下することでそれぞれの数字に値を1足す。
その後、合計値にという流れを実装したいのですが、うまくいきません。
合計値がボタンを押す前のNo1とNo2の合計値になってしまいます。
ソースは以下です。
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に値を直接いれる
これはあまりいけてないですが、パワープレイしたいならこちらが良いでしょう。
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
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の正しい使い方これであってるのかな・・・と不安になります。
一旦まとめて見ました。
他に案がある人募集しています。
教えて欲しいです・・・