javascript - 为什么 React 状态在第二次调用时不会改变?
问题描述
我目前正在构建一个利息计算器。的属性值calcInfo
可以通过滑块完美地更改,但是一旦我添加calculateResult()
任何值,将不再更改并使用默认值。
为什么会发生这种情况,我该如何解决?
const CalculatorContext = React.createContext();
const CalculatorProvider = (props) => {
const calculatorInformation = {
initial_investment: 10000,
monthly_contribution: 1000,
length_of_time_years: 40,
interest_rate_per_year: 7,
financial_data: [],
result: 2713059,
}
const [calcInfo, setCalcInfo] = useState(calculatorInformation);
const changeCalculation = (value, property) => {
console.log("-- hallo")
setCalcInfo({...calcInfo, [property]: value})
setCalcInfo({...calcInfo, financial_data: calculateResult()})
}
const calculateResult = () => {
const initial_investment = calcInfo.initial_investment
const contribution_per_month = calcInfo.monthly_contribution
const contribution_per_year = contribution_per_month * 12
const years = calcInfo.length_of_time_years
const interest_rate = parseFloat(calcInfo.interest_rate_per_year)
let result = initial_investment
const years_interests = []
const years_results = []
for (let year = 0; year < years; year++) {
result += contribution_per_year
result = result / 100 * (100 + interest_rate)
years_interests.push(year)
years_results.push(result)
}
const financial_data = {
labels: years_interests,
datasets: [{
label: 'Vermögensentwicklung über gewählten Zeitraum',
data: years_results,
}]
}
return financial_data
}
return (
<CalculatorContext.Provider value={{calcInfo, changeCalculation}}>
{props.children}
</CalculatorContext.Provider>
)
}
<input className="calculator-slider" type="range" min="1" max="100" step="1" value={length_of_time_years}
onChange={(e) => context.changeCalculation(parseInt(e.target.value), "length_of_time_years")}></input>
解决方案
按原样,您的状态设置函数已关闭当前版本的状态(截至该渲染)。确保您始终使用最新版本的状态的一种方法是使用回调函数:
const changeCalculation = (value, property) => {
setCalcInfo(c => ({...c, [property]: value}))
setCalcInfo(c => ({...c, financial_data: calculateResult()}))
}
编辑:顺便说一句,如果您需要计算结果calcInfo
内部的更新版本,我建议calcInfo
直接传递给calcuateResult
或者我猜想将其作为效果运行。
当然,最好的解决方案可能是根本不存储financial_data
在状态中,因为它是纯粹的派生状态,因此对于您的其他状态来说是多余的。
关于派生状态
编辑2:只是为了扩展我不存储的意思financial_data
。由于它是纯粹的派生状态,因此您可以随时从函数中获取此信息,而不是冗余地存储它。
因此,您可以在某处使此功能独立:
const getFinancialData = (calcInfo) => {
const initial_investment = calcInfo.initial_investment
const contribution_per_month = calcInfo.monthly_contribution
const contribution_per_year = contribution_per_month * 12
const years = calcInfo.length_of_time_years
const interest_rate = parseFloat(calcInfo.interest_rate_per_year)
let result = initial_investment
const years_interests = []
const years_results = []
for (let year = 0; year < years; year++) {
result += contribution_per_year
result = result / 100 * (100 + interest_rate)
years_interests.push(year)
years_results.push(result)
}
const financial_data = {
labels: years_interests,
datasets: [{
label: 'Vermögensentwicklung über gewählten Zeitraum',
data: years_results,
}]
}
return financial_data
}
然后,在您需要此信息的任何组件中,只需调用该函数。届时,您将始终拥有最新信息,而不必担心数据不同步:
const SomeComponent = () => {
const {calcInfo} = useContect(CalculatorContext);
// Purely derived state
const financialData = getFinancialData(calcInfo)
}
推荐阅读
- python - Nan的单元测试检查
- amazon-sqs - 有没有办法从标准 SQS 队列中接收大多数消息?[非先进先出]
- javascript - 未选择选择元素中的第二个选项时禁用按钮
- ruby - Ruby:在 Struct 中定义常量的语法
- android - BroadcastReceiver 没有收到广播事件消息
- r - 19 位数字不会像在 R 中那样被解析
- python - 如何在python中的某个单词之后提取字符串?
- python - 试图使它成为您可以从列表中选择书籍的地方,然后在最后使用 python 给出分项收据
- r - ggplot 清理堆积条形图上的 y 轴
- http - multipart/form-data 是一次性还是以流的形式发送整个文件数据