我有一个需要更新的应用程序组件数组挂钩,但我有一个无法更新的变量,不明白为什么。
应用程序组件代码:
function App() {
const [coins, setCoins] = useState([{name:'Shekel',price:2}, {name:'Dollar',price:3}, {name:'Rubal',price:20}])
const [changeHistory, setChangeHistory] = useState([])
const updateHistoryChange=(from,to,changeRate,amount)=>{
setChangeHistory([...changeHistory,{from:from,to:to,changeRate:changeRate,amout:amount,index:changeHistory.length}])
}
return (
<div className="App">
<Router>
<Switch>
<Route exact path="/" component={() => { return <HomePage coins={coins} updateHistoryChange={updateHistoryChange} />}}/>
</Switch>
</Router>
</div>
);
}
export default App;
主页组件:
export default function HomePage(props) {
const [inputMoney, setInputMoney] = useState()
const [from, setFrom] = useState()
const [to, setTo] = useState()
const [flag, setFlag] = useState(false)
const [rateChange,setRateChange]=useState()
const calculate = () => {
debugger
let sum = 0;
let fromChange;
let toChange;
for (let i = 0; i < props.coins.length; i++) {
if (props.coins[i].name == from) {
fromChange = props.coins[i].price;
break;
}
}
for (let i = 0; i < props.coins.length; i++) {
if (props.coins[i].name == to) {
toChange = props.coins[i].price;
setRateChange(toChange)//not updating it is always undefined
break;
}
}
sum = toChange * inputMoney;
console.log(`${rateChange}`);
props.updateHistoryChange(from,to,rateChange,inputMoney)
window.alert(`${sum}`);
}
const redirect = () => {
window.location.href = 'https://www.facebook.com/';
}
const isHid = () => {
if (flag) {
}
}
return (
<div>
<h1>Exchange</h1>
<p>From:<select id='from' onChange={(element) =>{setFrom(element.target.value)}}>
{props.coins.map((element) => {
return (
<option value={`${element.name}`} >
{element.name}
</option>
)
})}
</select>
<input type='number' placeholder='type your money amount' onChange={(element) => { setInputMoney(Number(element.target.value)) }}></input>
</p>
<p>
To:<select id='to' onChange={(element) => { setTo(element.target.value) }}>
{props.coins.map((element) => {
return (
<option value={`${element.name}`}>
{element.name}
</option>
)
})}
</select>
</p>
<button onClick={calculate} disabled={!inputMoney}>Start</button>
<button>Update</button>
<button onClick={redirect}>Share on facebook</button>
<button>View your exchange list</button>
{isHid()}
</div>
)
}
在函数计算中,当我设置
rateChange
时,如下所示:
setRateChange(toChange)
它没有更新我的钩子。
我也尝试过这个,但它也不起作用:
setRateChange(props.coins[i].price)
我已经解决了该问题并提供了以下解释。请找到工作链接 - https://stackblitz.com/edit/react-szjqbu?file=src/App.js
我想在这里向您解释两件事:-
React 批量更新组件状态,因此如果您在更新状态后尝试立即访问更新后的状态,您将无法获得更新后的状态。 由于您在调用
rateChange
后尝试立即访问日志中的状态变量 setRateChange
,因此您没有获得更新的值。
在
App.js
中定义 Route
; component
的 HomePage
属性是一种内联方法,它始终返回新的 HomePage
实例,这会导致状态重置,因为它是新组件,之前的组件已被卸载。
无法更新
rateChange
变量的原因是,当您调用 calculate
时,您会触发父组件的重新渲染,这会导致 HomePage
组件卸载然后重新挂载,这将重置rateChange
的状态为其初始值或默认值 undefined
。
要解决此问题,您需要确保
HomePage
未卸载。为此,您需要解决导致这种情况发生的原因。这是发生的事情:
props.updateHistoryChange
时,会在 App
中的父组件上调用设置状态,这会触发重新渲染App
上的重新渲染开始,这会导致检查其子级是否有更新HomePage
的路线,看看是否需要
重新渲染,因为 HomePage
组件作为
函数(没有记忆)react-router-dom
(我假设
这就是您正在使用的)看到一个新的 HomePage
组件并且
重新渲染一个新组件,卸载前一个组件,因为 component
属性已更改通过使用
useCallback
记忆组件
const updateHistoryChange = useCallback(
(from, to, changeRate, amount) => {
setChangeHistory((changeHistory) => [
...changeHistory,
{
from: from,
to: to,
changeRate: changeRate,
amout: amount,
index: changeHistory.length
}
]);
},
[setChangeHistory]
);
const HomePageRoute = useCallback(
() => <HomePage coins={coins} updateHistoryChange={updateHistoryChange} />,
[coins, updateHistoryChange]
);
return (
<div className="App">
<Router>
<Switch>
<Route exact path="/" component={HomePageRoute} />
</Switch>
</Router>
</div>
);
或者使用jsx
<Route exact path="/">
<HomePage coins={coins} updateHistoryChange={updateHistoryChange} />
</Route>
变量的状态变化将持续存在,这是实践中后者的codesandebox