stateの中のbmiに計算した数値を代入して保存したい
ユーザーが身長、体重を入れると、コードで計算をしてオブジェクトで定義したstateの中のbmiに保存できるようにしたい。
発生している問題・エラーメッセージ
setStateでbmiが保存されていない。ログを出してみるときちんとBMIは計算できていて、値が表示されていたので、以下の即時関数に問題がある可能性がある気がするが、原因がわからなかった。
react
1(function () { 2 const height_m = state.height / 100; 3 const total = parseFloat(state.weight / (height_m * height_m)); 4 const BMI = Math.round(total) 5 setState({ ...state, bmi: BMI }); 6 console.log(state) 7 }())
該当のソースコード(変更前)
react
1function Setting() { 2 const [state, setState] = useState({ 3 name: "", 4 old: "", 5 weight: "", 6 height: "", 7 introduction: "", 8 fat_percentage: "", 9 bmi: "", 10 }); 11 const handleChange = event => { 12 console.log(event.target.name) 13 setState({ ...state, [event.target.name]: event.target.value }); 14 }; 15 const handleSubmit = () => { 16 const currentUser = firebase.auth().currentUser; 17 (function () { 18 const height_m = state.height / 100; 19 const total = parseFloat(state.weight / (height_m * height_m)); 20 const BMI = Math.round(total) 21 setState({ ...state, bmi: BMI }); 22 console.log(state) 23 }()) 24 } 25 return ( 26 <React.Fragment> 27 <SchemerAppBar title="Setting" /> 28 <Container> 29 <form onSubmit={handleSubmit}> 30 <Grid> 31 <TextField name="name" width="180" label="名前" value={state.name} onChange={handleChange} style={{ marginRight: 20 }}></TextField> 32 <TextField 33 width="150" 34 label="年齢" 35 name="old" 36 defaultValue={state.old} 37 value={state.old} 38 onChange={handleChange} 39 InputProps={{ 40 endAdornment: <InputAdornment position="end">歳</InputAdornment>, 41 }}></TextField> 42 </Grid> 43 <Grid> 44 <TextField 45 name="height" 46 width="100" 47 label="身長" 48 value={state.height} 49 style={{ marginRight: 20 }} 50 onChange={handleChange} 51 InputProps={{ 52 endAdornment: <InputAdornment>cm</InputAdornment>, 53 }}></TextField> 54 <TextField 55 width="100" 56 label="体重" 57 name="weight" 58 value={state.weight} 59 onChange={handleChange} 60 InputProps={{ 61 endAdornment: <InputAdornment>Kg</InputAdornment>, 62 }} 63 ></TextField> 64 <TextField 65 width="100" 66 label="体脂肪率" 67 name="fat_percentage" 68 value={state.fat_percentage} 69 onChange={handleChange} 70 style={{ marginLeft: 20 }} 71 InputProps={{ 72 endAdornment: <InputAdornment>%</InputAdornment>, 73 }} 74 ></TextField> 75 </Grid> 76 <Grid> 77 <InputLabel style={{ marginTop: 20 }}>詳細</InputLabel> 78 <TextField 79 name="introduction" 80 width="400" 81 multiline rows={4} 82 variant="outlined" 83 value={state.introduction} 84 fullWidth 85 onChange={handleChange} 86 variant="outlined" 87 > 88 </TextField> 89 </Grid> 90 <Grid container justify="space-between"> 91 <Grid item> 92 </Grid> 93 <Grid item> 94 <Button 95 color="primary" 96 variant="contained" 97 style={{ marginTop: 20 }} 98 value="Submit" 99 type="submit" 100 > 101 登録する</Button> 102 </Grid> 103 </Grid> 104 </form> 105 </Container> 106 </React.Fragment> 107}
#変更後(formではなく、変更ボタンクリック次に呼び出すようにした)
react
1function Setting() { 2 const [state, setState] = useState({ 3 name: "", 4 old: "", 5 weight: "", 6 height: "", 7 introduction: "", 8 fat_percentage: "", 9 bmi: "", 10 }); 11const handleChange = event => { 12 console.log(event.target.name) 13 setState({ ...state, [event.target.name]: event.target.value }); 14 } 15 function calcBMI() { 16 const height_m = state.height / 100; 17 var total = parseFloat(state.weight / (height_m * height_m)); 18 const BMI = Math.round(total); 19 const newState = { ...state, bmi: BMI }; 20 setState(newState); 21 console.log(state); 22 } 23 function handleSubmit() { 24 const currentUser = firebase.auth().currentUser; 25 calcBMI(); 26 } 27 return ( 28 <React.Fragment> 29 <SchemerAppBar title="Setting" /> 30 <Container> 31 <Button 32 color="default" 33 variant="contained" 34 onClick={() => history.goBack()} 35 style={{ marginTop: 20 }} 36 >戻る 37 </Button> 38 <Grid> 39 <TextField name="name" width="180" label="名前" value={state.name} onChange={handleChange} style={{ marginRight: 20 }}></TextField> 40 <TextField 41 width="150" 42 label="年齢" 43 name="old" 44 value={state.old} 45 onChange={handleChange} 46 InputProps={{ 47 endAdornment: <InputAdornment position="end">歳</InputAdornment>, 48 }}></TextField> 49 </Grid> 50 <Grid> 51 <TextField 52 name="height" 53 width="100" 54 label="身長" 55 value={state.height} 56 style={{ marginRight: 20 }} 57 onChange={handleChange} 58 InputProps={{ 59 endAdornment: <InputAdornment>cm</InputAdornment>, 60 }}></TextField> 61 <TextField 62 width="100" 63 label="体重" 64 name="weight" 65 value={state.weight} 66 onChange={handleChange} 67 InputProps={{ 68 endAdornment: <InputAdornment>Kg</InputAdornment>, 69 }} 70 ></TextField> 71 <TextField 72 width="100" 73 label="体脂肪率" 74 name="fat_percentage" 75 value={state.fat_percentage} 76 onChange={handleChange} 77 style={{ marginRight: 20, marginLeft: 20 }} 78 InputProps={{ 79 endAdornment: <InputAdornment>%</InputAdornment>, 80 }} 81 ></TextField> 82 </Grid> 83 <Grid> 84 <InputLabel style={{ marginTop: 20 }}>詳細</InputLabel> 85 <TextField 86 name="introduction" 87 width="400" 88 multiline rows={4} 89 variant="outlined" 90 value={state.introduction} 91 fullWidth 92 onChange={handleChange} 93 variant="outlined" 94 > 95 </TextField> 96 </Grid> 97 <Grid container justify="space-between"> 98 <Grid item> 99 </Grid> 100 <Grid item> 101 <Button 102 color="primary" 103 variant="contained" 104 style={{ marginTop: 20 }} 105 value="Submit" 106 type="submit" 107 onClick={handleSubmit} 108 > 109 登録する</Button> 110 </Grid> 111 </Grid> 112 <LabelBottomNavigation /> 113 </Container> 114 </React.Fragment> 115 ); 116}
試したこと
handleSubmit関数の中でstateのログを出してみたところ、bmi以外はhandleSubmit内でstateが置き換えられていることがわかった。
即時関数内で、console.log(BMI)をすると、計算された値が表示された。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/03/09 06:51
2021/03/09 06:55
2021/03/09 13:15
2021/03/09 13:22
2021/03/10 06:25
2021/03/10 06:33
2021/03/11 05:27
2021/03/11 05:31
2021/03/11 09:38 編集