Реагировать на setState с обратным вызовом в функциональных компонентах

У меня есть очень простой пример, который я написал в компоненте класса:

    setErrorMessage(msg) {
      this.setState({error_message: msg}, () => {
          setTimeout(() => {
              this.setState({error_message: ''})
          }, 5000);
      });
    }

Итак, здесь я вызываю метод setState() и передаю ему обратный вызов в качестве второго аргумента.

Интересно, могу ли я сделать это внутри функционального компонента с помощью хука useState.

Насколько я знаю, вы не можете передать обратный вызов функции setState этого хука. А когда я использую хук useEffect - получается бесконечный цикл:

введите описание изображения здесь

Полагаю - этот функционал не входит в функциональные компоненты?


person Slowwie    schedule 16.05.2020    source источник


Ответы (1)


Функциональность обратного вызова недоступна в перехватчиках реакции, но вы можете написать простой способ обхода, используя useEffect и useRef.

const [errorMessage, setErrorMessage] = useState('')
const isChanged = useRef(false);
useEffect(() => {
   if(errorMessage) { // Add an existential condition so that useEffect doesn't run for empty message on first rendering
       setTimeout(() => {
          setErrorMessage('');
       }, 5000);
   }

}, [isChanged.current]); // Now the mutation will not run unless a re-render happens but setErrorMessage does create a re-render

const addErrorMessage = (msg) => {
  setErrorMessage(msg);
  isChanged.current = !isChanged.current; // intentionally trigger a change
}

В приведенном выше примере учитывается тот факт, что вы можете захотеть установить errorMessage из другого места, где вы не хотели бы его сбрасывать. Если, однако, вы хотите сбрасывать сообщение каждый раз, когда вы устанавливаете ErrorMessage, вы можете просто написать обычный useEffect, например

useEffect(() => {
    if(errorMessage !== ""){ // This check is very important, without it there will be an infinite loop
        setTimeout(() => {
              setErrorMessage('');
         }, 5000);
    }

}, [errorMessage]) 
person Shubham Khatri    schedule 16.05.2020
comment
Да, спасибо. Я нашел решение с помощью if (successCreatedCard! == {}) самостоятельно. А вот штука с useRef звучит интересно. Я еще не совсем понял это, но я выучу это. Спасибо. - person Slowwie; 16.05.2020