Реакция useCallback не обновляет состояние onChange при первом изменении - PullRequest
0 голосов
/ 07 апреля 2020

Я пытаюсь создать выпадающий список поиска, но мой поисковый фильтр не обновляется должным образом с помощью useCallback. Обратный вызов 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>

Я смог исправить эту ошибку, убрав обратный вызов:

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

Что не так с моей реализацией из useCallback?

Я даже пытался добавить ref в логи c, но это не сработало. Я прочитал в документации по React многие входные изменения, которые они предпочитают использовать с помощью ссылок:

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 Я пытался добавить фрагмент JS, но, похоже, я пока не могу добавить обработчики реакции в stackoverflow. Нужно обрабатывать версии React 16.8+. Если есть способ, которым я могу это сделать, пожалуйста, дайте мне знать.

Ответы [ 2 ]

2 голосов
/ 07 апреля 2020

Кажется, у меня работает, какое значение не обновляется? Значение ввода или отображаемые параметры?

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

0 голосов
/ 07 апреля 2020

React может объединять несколько вызовов setState () в одно обновление для повышения производительности. Поскольку this.props и this.state могут обновляться асинхронно, вы не должны полагаться на их значения для вычисления следующего состояния.

Например, этот код может не обновить счетчик:

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

Чтобы исправить это, используйте вторую форму setState (), которая принимает функцию, а не объект. Эта функция получит предыдущее состояние в качестве первого аргумента, а реквизиты во время применения обновления в качестве второго аргумента:

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

Проверьте эту страницу на реакцию: состояние и жизненный цикл обновления состояния Может быть асинхронным

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...