Получить значение после изменения стейта

У меня есть стейт предположим:

const [ fields, setFields ] = useState(
    {
        field1: { error: "" },
        field2: { error: "" },
        field3: { error: "" }
    }
);

Мне его нужно изменить (в моем случае это валидация) и следом проверить значения, абстрактный код:

const onFormSubmit: (event: FormEvent<HTMLFormElement>) => void = (event) =>
{
    event.preventDefault()

    // делаем какую-то валидацию
    setFields((prevState) => (
        {
            ...prevState,
            field1:
            {
                ...prevState[ prevState ],
                error: "Test"
            }
        }
    ));

    // Если у нас есть ошибки, мы не выполняем дальше код
    if (fields.field1.error !== "")
    {
        // какой-то код
        return;
    }

    console.info("submit");
}

У меня не заходит в блок с if, я понимаю, что реакт это делает асинхронно, но как мне увидеть изменения в этом же блоке?


Ответы (1 шт):

Автор решения: xydope

У вас есть 2 варианта.

  1. Использовать классовый компонент, в котором ф-я обновления состояния this.setState принимает 2 аргумента, 1 - новое состояние, 2 - коллбек ф-ю, которая будет вызвана после обновления состояния (см. пример ниже)

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      value: 0
    }
  }

  increment() {
    this.setState(({
      value
    }) => ({
      value: value + 1
    }), () => {
      //сделать что-то, после обновления стейта
      console.log('State updated ' + this.state.value)
    })
  }

  render() {
    return <button onClick = {
      this.increment.bind(this)
    } > {
      this.state.value
    } < /button>
  }
}

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

  1. Использовать хук useEffect в функциональном компоненте

const App = () => {
  const [value, setValue] = React.useState(0)

  React.useEffect(() => {
    //Чтобы не выполнять при первом рендере можно исключить состояние инициализации
    const isFirstRender = !value
    if (!isFirstRender) {
      //сделать что-то после обновления value
      console.log('Value is Updated: ' + value)
    }
  }, [value])

  return <button onClick = {
    () => setValue((prev) => prev + 1)
  } > {
    value
  } < /button>
}

ReactDOM.render( < App / > , document.getElementById('app'))
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<div id="app"></div>

→ Ссылка