为什么 React 状态在第二次调用时不会改变?
Why does React state not change when called a second time?
我目前正在构建一个利息计算器。 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
inside of 计算结果的更新版本,我推荐将 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)
}
我目前正在构建一个利息计算器。 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
inside of 计算结果的更新版本,我推荐将 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)
}