Ind*_*ana 3 reactjs react-hooks
我正在寻找一种使用 React Hooks 计算依赖于其他状态值的状态值的方法。
我正在熟悉 React Hooks。到目前为止,我一直在使用 useState 和 useEffect。我知道其他钩子,例如 useReduce、useCallback 等。
我制作了一个简单的费率计算器,可以按小时、每周、每月和每年转换费率。当我更改相应的费率时,其他费率将相应更新。
该应用程序的代码如下:
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 />
<div className={classes.paper}>
<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)}
/>
</div>
</Container>
);
}
export default App;
Run Code Online (Sandbox Code Playgroud)
代码沙盒链接 - tryConvert
该应用程序按预期工作,据我测试,尚未在边缘情况下工作。
简化汇率转换
我正在尝试tryConvert使用其他 React Hooks简化转换,但没有成功。这是从上面的代码转换的代码:
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);
}
};
Run Code Online (Sandbox Code Playgroud)
我尝试使用 useEffect
我尝试过的是使用 useEffect 在状态更改时添加回调。下面的代码说明了我的尝试:
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]);
Run Code Online (Sandbox Code Playgroud)
如果我使用这种方法,当我更改workHour转换时将无法按预期工作。我认为是因为workHour4 个不同的useEffect. 我仍然不确定这一点。
代码沙盒链接 - useEffect
如果您更改工作时间,则转换将不起作用
目前,我正在尝试使用 useReduce 的其他方法,但我仍然不确定这是否是转换费率的最佳方式。
简化我的 tryConvert 的最佳方法是什么?
我将不胜感激。
这里真的没有必要useEffect。useEffect用于副作用(例如setInterval,document.title不属于渲染周期的东西)。
您的第一个解决方案工作正常,但您可以通过为汇率提供单一真实来源并根据该数据计算其他汇率来简化它。像这样的东西:
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 (
<div className={classes.paper}>
<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")}
/>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
对于一个工作示例,这里有一个代码和框:https ://codesandbox.io/s/rate-kalkulator-ej5m8
| 归档时间: |
|
| 查看次数: |
1494 次 |
| 最近记录: |