简体   繁体   English

在第一次更改时反应 useCallback 不更新 state onChange

[英]React useCallback not updating state onChange on the first change

I'm trying to create a search dropdown list but my search filter is not being updated properly with useCallback .我正在尝试创建一个搜索下拉列表,但我的搜索过滤器没有使用useCallback正确更新。 The searchFilter callback does not update values on the first onChange searchFilter 回调不会更新第一个onChange的值

const [inputValue, setInputValue] = useState('');
const [opts, setOpts] = useState(allOptions);

const searchFilter = useCallback(
    (val) => {
        setInputValue(val);
        const filter = val.toUpperCase();
        const ops = options.filter((opt) => opt.text.toUpperCase().indexOf(filter) > -1);
        setOpts(ops);
    }, [inputValue] // state not being updated on first onChange
);

<textArea
    onChange={(e) => searchFilter(e.target.value)}
    value={inputValue}
/>

<ul>
    {opts.map((option) => (
        <li key={option.key}>
            {option.text}
        </li>
    ))}
</ul>

I was able to fix this bug by taking out the callback:我能够通过取出回调来修复这个错误:

const searchFilter = (val) => {
    setInputValue(val);
    const filter = val.toUpperCase();
    const ops = options.filter((opt) => opt.text.toUpperCase().indexOf(filter) > -1);
    setOpts(ops);
} // this works on every onChange

What is wrong with my implementation of useCallback ?我的useCallback实现有什么问题?

I even tried adding a ref to the logic but that didn't work.我什至尝试在逻辑中添加一个ref ,但这没有用。 I read in the React docs for many input changes they prefer using refs:我在 React 文档中阅读了他们喜欢使用 refs 的许多输入更改:

const [inputValue, setInputValue] = useState('');
const [opts, setOpts] = useState(allOptions);
const inputEl = useRef(null);

useEffect(() => {
    inputEl.current = inputValue; // Write it to the ref
});

const searchFilter = useCallback(
    (val) => {
        setInputValue(val);
        const filter = val.toUpperCase();
        const ops = options.filter((opt) => opt.text.toUpperCase().indexOf(filter) > -1);
        setOpts(ops);
    }, [inputEl]
);

<textArea
    ref={inputEl}
    onChange={(e) => searchFilter(e.target.value)}
    value={inputValue}
/>

** note I tried adding a JS snippet but it seems I can't add react hooks to stackoverflow yet. ** 注意我尝试添加一个 JS 片段,但似乎我还不能将反应钩子添加到 stackoverflow。 Needs to handle React versions 16.8+.需要处理 React 16.8+ 版本。 If there is a way I can do it please let me know.如果有办法我可以做到,请告诉我。

It seems to work for me, what value is it that's not updating?它似乎对我有用,不更新的价值是什么? The input value or the displayed options?输入值还是显示的选项?

https://codesandbox.io/s/brave-mcnulty-pysjj https://codesandbox.io/s/brave-mcnulty-pysjj

React may batch multiple setState() calls into a single update for performance. React 可以将多个 setState() 调用批处理到单个更新中以提高性能。 Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.因为 this.props 和 this.state 可能会异步更新,所以您不应依赖它们的值来计算下一个 state。

For example, this code may fail to update the counter:例如,此代码可能无法更新计数器:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

To fix it, use a second form of setState() that accepts a function rather than an object.要修复它,请使用第二种形式的 setState(),它接受 function 而不是 object。 That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument: function 将接收之前的 state 作为第一个参数,并且在应用更新时的道具作为第二个参数:

// Correct
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

Check this page about react: State and Lifecycle State Updates May Be Asynchronous检查此页面关于反应:State 和生命周期State 更新可能是异步的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM