input/useState 可以不在按钮点击时设置吗?

Possible for input/useState not to be set on button click?

我是否需要担心 fetchClassesSearchedByName(searchName); 不会有 searchName 值?我的按钮点击速度是否可能比设置的 searchName 快?

// On input
const [searchName, setSearchName] = useState('');

// Text input
<input
    type='text'
    value={searchName}
    onChange={(e) => setSearchName(e.target.value)}
/>

// On button click
const searchNameBtn = (e) => {
        fetchClassesSearchedByName(searchName);
}

谢谢

setState 是异步的,所以如果你有西部老枪手的反应能力,这是可能的。

不过,您的默认值为 '',因此我认为只要 fetchClassesSearchedByName 可以采用空字符串,您就不需要任何错误处理。

Do I need to worry that fetchClassesSearchedByName(searchName); will not have a searchName value?

您已经定义了初始 searchName 状态并且所有 setSearchName 调用都传递了有效的定义值。只要所有状态更新都是有效的定义值,就没有机会在没有定义的 searchName 值的情况下调用 fetchClassesSearchedByName

Is it possible my button click is faster than searchName being set?

是的,这完全有可能,BUT也完全不现实。这是可能的,因为 React 状态更新不是立即的,而是排队和异步处理的。

考虑以下示例。有两个带有 onChange 处理程序的输入。

  • 输入和处理程序 #1: 第一个输入尝试模拟在状态更新排队后立即单击按钮,但由于 Javascript 外壳和事件循环工作,按钮的 onClick 事件在 之前被处理 React 处理状态更新,因为它在 onChange 处理函数的范围内是同步的。 fetchClassesSearchedByName 似乎是“延迟渲染周期”,因为它正在记录未更新的状态。
  • 输入和处理程序 #2: 第二个输入尝试模拟在状态更新入队后立即单击按钮,但使用的 setTimeout 为 0。这将放置事件队列末尾的点击事件回调。请注意,这是最早可能的按钮,甚至可以在 状态更新排队后 单击。 React 的状态更新处理完毕,然后处理点击事件。请注意,fetchClassesSearchedByName 现在总是看到更新后的 React 状态。

const fetchClassesSearchedByName = (value) => console.log(value);

function App() {
  const buttonRef = React.useRef();
  const [searchName, setSearchName] = React.useState("");

  const changeHandler1 = (e) => {
    setSearchName(e.target.value);
    buttonRef.current.click();
  };

  const changeHandler2 = (e) => {
    setSearchName(e.target.value);
    setTimeout(() => {
      buttonRef.current.click();
    }, 0);
  };

  const searchNameBtn = (e) => {
    fetchClassesSearchedByName(searchName);
  };

  return (
    <div className="App">
      <div>
        <label>
          Input 1 w/ synchronous button click
          <input type="text" value={searchName} onChange={changeHandler1} />
        </label>
      </div>
      <div>
        <label>
          Input 2 w/ asynchronous button click
          <input type="text" value={searchName} onChange={changeHandler2} />
        </label>
      </div>

      <div>
        <button ref={buttonRef} type="button" onClick={searchNameBtn}>
          Click me
        </button>
      </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <App />,
  rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root" />