使用自定义钩子时,我如何在useEffect调用之前获得当前值?

  • 本文关键字:调用 useEffect 自定义 reactjs
  • 更新时间 :
  • 英文 :


我的状态更新顺序有这个问题。有一个数据源,其中包含一些由键存储的值,这些值通过WebSocket不断更新。我已经做了一个自定义钩子,从数据源设置初始值并订阅套接字更新-并在任何相关更新时调用setState。

然后我有一个数字输入的表单,它使用当前数据源值作为初始表单输入值。例如,在组件呈现时,数据源提供值"345",然后用户可以编辑它(增加/减少)。

现在,当用户选择不同的数据源时,输入值应该再次重置为当前数据源值—但仅作为显式用户操作的结果—按下数据源切换按钮。在每次更改套接字时重置它将使表单输入不可用。

问题是当我改变数据源键时,从自定义钩子返回的值是旧的(它只在useEffect中改变)。

下面是代码示例:

import React, { useEffect, useState } from "react";
// some data source, which has initial values and is constantly updated from socket
const data = {
  one: 12345,
  two: 23456,
};
// a simplified version of hook, which gets current value
// and subscribes to socket updates
const useMyHook = (key) => {
  const [state, setState] = useState(data[key]);
  useEffect(() => {
    // set current state
    setState(data[key]);
    // subscribes/unsubscribes to socket updates, omitted for simplicity
    // ...
  }, [key]);
  return state;
};
export default function App() {
  const [dataSource, setDataSource] = useState("one");
  const dataSourceValue = useMyHook(dataSource);
  const [fieldValue, setFieldValue] = useState(dataSourceValue);
  const handleDataSourceToggle = (e) => {
    e.preventDefault();
    setDataSource(dataSource === "one" ? "two" : "one");
  };
  const handleUserInput = (e) => {
    setFieldValue(e.target.value);
  };
  // input value reset - please note, that I cannot use dataSourceValue as a dependency here
  // because I don't want to lose the value entered by user - only when he explicitly changes the data source
  useEffect(() => {
    setFieldValue(dataSourceValue);
  }, [dataSource]);
  return (
    <div className="App">
      <h1>Custom Hook Example</h1>
      <form>
        <p>
          <input type="number" value={fieldValue} onChange={handleUserInput} />
        </p>
        <p>
          Data source: <strong>{dataSource}</strong>
        </p>
        <p>
          Data source value: <strong>{dataSourceValue}</strong>
        </p>
        <button onClick={handleDataSourceToggle}>Change data source</button>
      </form>
    </div>
  );
}

这个例子是有意简化的,实际上数据源是在一些外部组件中切换的,当前组件从React context prop接收它。

如何解决这个问题?

这是沙盒:https://codesandbox.io/s/elated-brook-r9iubv?file=/src/App.js

现在,当用户选择不同的数据源时,输入值应该再次重置为当前数据源值-但仅作为显式用户操作的结果-按下数据源切换按钮。在每次更改套接字时重置它将使表单输入不可用。

这不是React可以猜测的东西,你必须明确地说(程序)哪些事件应该改变fieldValue,例如通过在handleDataSourceToggle回调中添加另一个setFieldValue

你也应该避免这样:

  // input value reset - please note, that I cannot use dataSourceValue as a dependency here
  // because I don't want to lose the value entered by user - only when he explicitly changes the data source
  useEffect(() => {
    setFieldValue(dataSourceValue);
  }, [dataSource]);

你将得到eslint警告,因为这不是应该使用的效果。如果您觉得需要省略一些依赖项,那么很可能意味着您应该以不同的方式编写代码。在这种情况下,我认为你根本不需要这种效果。

相关内容

  • 没有找到相关文章

最新更新