用变量设置钩子

问题描述 投票:0回答:2

我有一个需要更新的应用程序组件数组挂钩,但我有一个无法更新的变量,不明白为什么。

应用程序组件代码:

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)
reactjs react-hooks
2个回答
0
投票

我已经解决了该问题并提供了以下解释。请找到工作链接 - https://stackblitz.com/edit/react-szjqbu?file=src/App.js

我想在这里向您解释两件事:-

  1. React 批量更新组件状态,因此如果您在更新状态后尝试立即访问更新后的状态,您将无法获得更新后的状态。 由于您在调用

    rateChange
    后尝试立即访问日志中的状态变量
    setRateChange
    ,因此您没有获得更新的值。

  2. App.js
    中定义
    Route
    component
    HomePage
    属性是一种内联方法,它始终返回新的
    HomePage
    实例,这会导致状态重置,因为它是新组件,之前的组件已被卸载。


0
投票

无法更新

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

© www.soinside.com 2019 - 2024. All rights reserved.