React功能组件,useState回调不使用useEffect
React functional component, useState call back without using useEffect
我是 reactJS 的新手,可能遇到了过于复杂的事情或者没有正确计划。
我在使用 useState 挂钩跟踪项目中的属性时遇到了问题。
好的,开始了
由于使用 react-hook-form
,value
取自输入文本框作为文本类型
然后检查 type
,看它是否等于“收入”或“支出”
- If
type == "income"
then just set the value
using setValue
without any changes, else if type == "expense"
then *=-1
and set value
使用 setValue
parseInt()
与 setValue
一起使用以确保将值保存为数字
调用 setRecords
将相关信息添加到 record
对象数组中。
所以从上面的 5 个步骤可以看出,useState hook setValue
和 setRecords
被一个接一个地调用,我现在遇到的问题是应用程序的初始 运行,value
将追加而不是添加。
据我了解,因为 useState 挂钩是异步的,不会立即 return 结果,所以在 setRecords
被调用时, value
仍然是类型文本而不是数字
我已经在网上搜索了一段时间,但没有找到解决这个问题的好方法,没有使用 useEffect 钩子,我尝试使用 useEffect 钩子,但我没能成功,用户可以输入相同的 value
并且应用仍应将该值附加到 record
对象数组中。
最后,我决定新建一个属性 currentValue
并设置在form submit 上,因为这不是状态,会立即更新,不用等待setValue
更新 value
状态。
有没有更好的方法来解决这个问题?或者解决方法可以吗?
import React, { useEffect, useContext } from "react";
import RecordList from "./RecordList";
import { useForm } from "react-hook-form";
import { BudgetPlannerContext } from "../context/BudgetPlannerContext";
const BudgetPlanner = () => {
const { register, handleSubmit, errors } = useForm();
const [
records,
setRecords,
total,
setTotal,
type,
setType,
value,
setValue,
description,
setDescription,
] = useContext(BudgetPlannerContext);
let currentValue = 0;
useEffect(() => {
setTotal(() =>
records.reduce((acc, curr) => {
return acc + curr.value;
}, 0)
);
}, [records, setTotal]);
const onFormSubmit = (data) => {
if ((type === "Income") & (data.value !== 0)) {
currentValue = parseInt(data.value);
setValue(parseInt(data.value));
} else if ((type === "Expense") & (data.value !== 0)) {
currentValue = parseInt((data.value *= -1));
setValue(parseInt((data.value *= -1)));
} else {
return null;
}
setDescription(data.description);
processValue(type, currentValue);
};
const processValue = (type, currentValue) => {
updateRecord(type, currentValue);
//setValue(0);
//setDescription("");
//console.log(records);
};
const updateRecord = (type, currentValue) => {
setRecords((oldRecord) => [
...oldRecord,
{
type: type,
value: currentValue,
description: description,
id: Math.random() * 1000,
},
]);
};
return (
<div className="ui segment">
<div className="search-bar ui segment">
<form className="ui form" onSubmit={handleSubmit(onFormSubmit)}>
<div className="field">
<select
onChange={(e) => setType(e.target.value)}
name="todos"
ref={register}
className="filter-todo"
>
<option value="" defaultValue="defaultValue">
---
</option>
<option value="Income">Income</option>
<option value="Expense">Expense</option>
</select>
<input
name="description"
type="text"
placeholder="Description"
ref={register}
/>
<input
name="value"
type="number"
placeholder="Value"
ref={register}
/>
</div>
<div>Total: {total}</div>
<button type="submit">Submit</button>
</form>
</div>
<RecordList records={records} setRecords={setRecords} />
</div>
);
};
export default BudgetPlanner;
如果我是你,我会将新值作为参数传递给你正在调用的其他函数:
const onFormSubmit = (data) => {
if (data.value === 0 || (type !== 'Income' && type !== 'Expense')) {
return;
}
const newValue = parseInt(data.value) * (type === 'Income' ? 1 : -1);
setValue(newValue);
setDescription(data.description);
processValue(type, newValue);
};
不需要额外的外部变量。
另一种选择是使用 useEffect
(或者,最好是 useLayoutEffect
)并在 value
更改时调用 processValue
:
const onFormSubmit = (data) => {
if (data.value === 0 || (type !== 'Income' && type !== 'Expense')) {
return;
}
const newValue = parseInt(data.value) * (type === 'Income' ? 1 : -1);
setValue(newValue);
setDescription(data.description);
};
useLayoutEffect(() => {
if (value) {
processValue(type);
}
}, [value]);
并让 processValue
使用外部 value
有状态变量。
我是 reactJS 的新手,可能遇到了过于复杂的事情或者没有正确计划。
我在使用 useState 挂钩跟踪项目中的属性时遇到了问题。
好的,开始了
-
由于使用
value
取自输入文本框作为文本类型 然后检查type
,看它是否等于“收入”或“支出”- If
type == "income"
then just set thevalue
usingsetValue
without any changes, else iftype == "expense"
then*=-1
and setvalue
使用setValue
parseInt()
与setValue
一起使用以确保将值保存为数字
调用 setRecords
将相关信息添加到record
对象数组中。
react-hook-form
,所以从上面的 5 个步骤可以看出,useState hook setValue
和 setRecords
被一个接一个地调用,我现在遇到的问题是应用程序的初始 运行,value
将追加而不是添加。
据我了解,因为 useState 挂钩是异步的,不会立即 return 结果,所以在 setRecords
被调用时, value
仍然是类型文本而不是数字
我已经在网上搜索了一段时间,但没有找到解决这个问题的好方法,没有使用 useEffect 钩子,我尝试使用 useEffect 钩子,但我没能成功,用户可以输入相同的 value
并且应用仍应将该值附加到 record
对象数组中。
最后,我决定新建一个属性 currentValue
并设置在form submit 上,因为这不是状态,会立即更新,不用等待setValue
更新 value
状态。
有没有更好的方法来解决这个问题?或者解决方法可以吗?
import React, { useEffect, useContext } from "react";
import RecordList from "./RecordList";
import { useForm } from "react-hook-form";
import { BudgetPlannerContext } from "../context/BudgetPlannerContext";
const BudgetPlanner = () => {
const { register, handleSubmit, errors } = useForm();
const [
records,
setRecords,
total,
setTotal,
type,
setType,
value,
setValue,
description,
setDescription,
] = useContext(BudgetPlannerContext);
let currentValue = 0;
useEffect(() => {
setTotal(() =>
records.reduce((acc, curr) => {
return acc + curr.value;
}, 0)
);
}, [records, setTotal]);
const onFormSubmit = (data) => {
if ((type === "Income") & (data.value !== 0)) {
currentValue = parseInt(data.value);
setValue(parseInt(data.value));
} else if ((type === "Expense") & (data.value !== 0)) {
currentValue = parseInt((data.value *= -1));
setValue(parseInt((data.value *= -1)));
} else {
return null;
}
setDescription(data.description);
processValue(type, currentValue);
};
const processValue = (type, currentValue) => {
updateRecord(type, currentValue);
//setValue(0);
//setDescription("");
//console.log(records);
};
const updateRecord = (type, currentValue) => {
setRecords((oldRecord) => [
...oldRecord,
{
type: type,
value: currentValue,
description: description,
id: Math.random() * 1000,
},
]);
};
return (
<div className="ui segment">
<div className="search-bar ui segment">
<form className="ui form" onSubmit={handleSubmit(onFormSubmit)}>
<div className="field">
<select
onChange={(e) => setType(e.target.value)}
name="todos"
ref={register}
className="filter-todo"
>
<option value="" defaultValue="defaultValue">
---
</option>
<option value="Income">Income</option>
<option value="Expense">Expense</option>
</select>
<input
name="description"
type="text"
placeholder="Description"
ref={register}
/>
<input
name="value"
type="number"
placeholder="Value"
ref={register}
/>
</div>
<div>Total: {total}</div>
<button type="submit">Submit</button>
</form>
</div>
<RecordList records={records} setRecords={setRecords} />
</div>
);
};
export default BudgetPlanner;
如果我是你,我会将新值作为参数传递给你正在调用的其他函数:
const onFormSubmit = (data) => {
if (data.value === 0 || (type !== 'Income' && type !== 'Expense')) {
return;
}
const newValue = parseInt(data.value) * (type === 'Income' ? 1 : -1);
setValue(newValue);
setDescription(data.description);
processValue(type, newValue);
};
不需要额外的外部变量。
另一种选择是使用 useEffect
(或者,最好是 useLayoutEffect
)并在 value
更改时调用 processValue
:
const onFormSubmit = (data) => {
if (data.value === 0 || (type !== 'Income' && type !== 'Expense')) {
return;
}
const newValue = parseInt(data.value) * (type === 'Income' ? 1 : -1);
setValue(newValue);
setDescription(data.description);
};
useLayoutEffect(() => {
if (value) {
processValue(type);
}
}, [value]);
并让 processValue
使用外部 value
有状态变量。