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" />
我是否需要担心 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 asearchName
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" />