React Hooks: Is there a way to calculate state values based on another state value
我正在寻找一种使用React Hooks计算依赖于其他状态值的状态值的方法。
我已经熟悉React Hooks。到目前为止,我一直在使用useState和useEffect。我知道其他钩子例如useReduce,useCallback等。
我已经制作了一个简单的费率计算器,可以每小时,每周,每月和每年转换费率。当我更改各自的费率时,其他费率也将相应更新。
该应用的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | import React, { useState } from 'react'; import { CssBaseline, Container, Typography, TextField } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; const useStyles = makeStyles(theme => ({ paper: { marginTop: theme.spacing(8), // = 4 * 2 display: 'flex', flexDirection: 'column', alignItems: 'center' } })); function App() { const classes = useStyles(); const [hourlyRate, setHourlyRate] = useState(10); const [workHour, setWorkHour] = useState(40); const [weeklyRate, setWeeklyRate] = useState(400); const [monthlyRate, setMonthlyRate] = useState(1600); const [yearlyRate, setYearlyRate] = useState(19200); const tryConvert = ({ name, value }) => { if (name === 'work-hours') { setWorkHour(value); setWeeklyRate(value * hourlyRate); setMonthlyRate(value * hourlyRate * 4); setYearlyRate(value * hourlyRate * 4 * 12); } else if (name === 'hourly-rate') { setHourlyRate(value); setWeeklyRate(value * workHour); setMonthlyRate(value * workHour * 4); setYearlyRate(value * workHour * 4 * 12); } else if (name === 'weekly-rate') { setWeeklyRate(value); setHourlyRate(value / workHour); setMonthlyRate(value * 4); setYearlyRate(value * 4 * 12); } else if (name === 'monthly-rate') { setMonthlyRate(value); setWeeklyRate(value / 4); setHourlyRate(value / workHour / 4); setYearlyRate(value * 12); } else if (name === 'yearly-rate') { setYearlyRate(value); setMonthlyRate(value / 12); setWeeklyRate(value / 12 / 4); setHourlyRate(value / 12 / 4 / workHour); } }; return ( <Container component="main" maxWidth="xs"> <CssBaseline /> <Typography component="h1" variant="h5"> Rate Kalkulator </Typography> <TextField variant="outlined" margin="normal" id="hourly-rate" label="Hourly Rate" name="hourly-rate" autoFocus inputProps={{ 'data-testid': 'hourly-rate' }} value={hourlyRate ? hourlyRate : 0} onChange={event => tryConvert(event.target)} /> <TextField variant="outlined" margin="normal" id="work-hours" label="Work Hours" name="work-hours" inputProps={{ 'data-testid': 'work-hours' }} value={workHour} onChange={event => tryConvert(event.target)} /> <TextField variant="outlined" margin="normal" id="weekly-rate" label="Weekly Rate" name="weekly-rate" inputProps={{ 'data-testid': 'weekly-rate' }} value={weeklyRate ? weeklyRate : 0} onChange={event => tryConvert(event.target)} /> <TextField variant="outlined" margin="normal" id="monthly-rate" label="Monthly Rate" name="monthly-rate" inputProps={{ 'data-testid': 'monthly-rate' }} value={monthlyRate ? monthlyRate : 0} onChange={event => tryConvert(event.target)} /> <TextField variant="outlined" margin="normal" id="yearly-rate" label="Yearly Rate" name="yearly-rate" inputProps={{ 'data-testid': 'yearly-rate' }} value={yearlyRate ? yearlyRate : 0} onChange={event => tryConvert(event.target)} /> </Container> ); } export default App; |
Codesandbox链接-
费率追踪器-tryConvert
据我测试,该应用程序按预期工作,尚未在边缘情况下工作。
简化速率转换
我正在尝试与其他React Hooks简化转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | const tryConvert = ({ name, value }) => { if (name === 'work-hours') { setWorkHour(value); setWeeklyRate(value * hourlyRate); setMonthlyRate(value * hourlyRate * 4); setYearlyRate(value * hourlyRate * 4 * 12); } else if (name === 'hourly-rate') { setHourlyRate(value); setWeeklyRate(value * workHour); setMonthlyRate(value * workHour * 4); setYearlyRate(value * workHour * 4 * 12); } else if (name === 'weekly-rate') { setWeeklyRate(value); setHourlyRate(value / workHour); setMonthlyRate(value * 4); setYearlyRate(value * 4 * 12); } else if (name === 'monthly-rate') { setMonthlyRate(value); setWeeklyRate(value / 4); setHourlyRate(value / workHour / 4); setYearlyRate(value * 12); } else if (name === 'yearly-rate') { setYearlyRate(value); setMonthlyRate(value / 12); setWeeklyRate(value / 12 / 4); setHourlyRate(value / 12 / 4 / workHour); } }; |
我尝试使用useEffect
我尝试过的是在状态更改时使用useEffect添加回调。以下代码说明了我尝试过的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import React, { useState, useEffect } from 'react'; const [hourlyRate, setHourlyRate] = useState(10); const [workHour, setWorkHour] = useState(40); const [weeklyRate, setWeeklyRate] = useState(400); const [monthlyRate, setMonthlyRate] = useState(1600); const [yearlyRate, setYearlyRate] = useState(19200); useEffect(() => { setWeeklyRate(hourlyRate * workHour); setMonthlyRate(hourlyRate * workHour * 4); setYearlyRate(hourlyRate * workHour * 4 * 12); }, [hourlyRate, workHour]); useEffect(() => { setHourlyRate(weeklyRate / workHour); setMonthlyRate(weeklyRate * 4); setYearlyRate(weeklyRate * 4 * 12); }, [weeklyRate, workHour]); useEffect(() => { setHourlyRate(monthlyRate / 4 / workHour); setWeeklyRate(monthlyRate / 4); setYearlyRate(monthlyRate * 12); }, [monthlyRate, workHour]); useEffect(() => { setHourlyRate(yearlyRate / 12 / 4 / workHour); setWeeklyRate(yearlyRate / 12 / 4); setMonthlyRate(yearlyRate / 12); }, [yearlyRate, workHour]); |
如果使用这种方法,则当我更改
Codesandbox链接-useEffect
费率追踪器-useEffect
如果您更改工作时间,则转换将无效
当前,我正在尝试使用useReduce的其他方法,但是我仍然不确定这是否是转换费率的最佳方法。
简化我的tryConvert的最佳方法是什么?
在此方面,我将不胜感激。
这里确实不需要
您的第一个解决方案可以很好地工作,但是您可以通过使用单一的真实费率来源并根据该费率计算其他费率来简化此解决方案。像这样的东西:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | function App() { const classes = useStyles(); const [hourlyRate, setHourlyRate] = useState(10); const [workHour, setWorkHour] = useState(40); const convertTo = name => { const map = { weekly: hourlyRate * workHour, monthly: hourlyRate * workHour * 4, yearly: hourlyRate * workHour * 52 }; return map[name] || 0; }; const convertFrom = name => e => { const { value } = e.target; const map = { weekly: value / workHour, monthly: value / workHour / 4, yearly: value / workHour / 52 }; setHourlyRate(map[name]); }; return ( <Typography component="h1" variant="h5"> Rate Kalkulator </Typography> <TextField label="Hourly Rate" value={hourlyRate || 0} onChange={e => setHourlyRate(e.target.value)} /> <TextField label="Work Hours" value={workHour} onChange={e => setWorkHour(e.target.value)} /> <TextField label="Weekly Rate" value={convertTo("weekly") || 0} onChange={convertFrom("weekly")} /> <TextField label="Monthly Rate" value={convertTo("monthly") || 0} onChange={convertFrom("monthly")} /> <TextField label="Yearly Rate" value={convertTo("yearly") || 0} onChange={convertFrom("yearly")} /> ); } |
对于一个工作示例,这是一个代码框:https://codesandbox.io/s/rate-kalkulator-ej5m8