用变量设置钩子

时间:2021-02-20 09:35:57

标签: reactjs react-hooks

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

应用组件代码

struct MyPopover: View {
    let number: Int
    let item: PopoverItem
    var body: some View {
        HStack {
            Text("\(number)")
            Text(item.text)
        }.padding()
    }
}

struct PopoverItem: Identifiable {
    let id = UUID()
    let text: String
    
    init(_ text: String) { self.text = text }
}

主页组件

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;

在函数中计算我何时设置 rateChange 像这样:

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 undifined
                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>
    )
}

它没有更新我的钩子 也试过这不起作用:

setRateChange(props.coins[i].price)

2 个答案:

答案 0 :(得分:0)

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

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

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

  2. 在您定义 App.jsRoute 中; componentHomePage prop 是一个内联方法,它总是返回新的 HomePage 实例,这会导致状态重置,因为它是新组件之前的组件被卸载。

答案 1 :(得分: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