I
I
Ivan Ivanovich2021-10-28 09:51:33
React
Ivan Ivanovich, 2021-10-28 09:51:33

Why does useState work like this?

Good day.

There is a component:

import { useEffect, useState } from 'react';

import { getRandomIntInRange } from './utills';

const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

const Test = () => {
  const [test] = useState(() => getRandomIntInRange(0, arr.length - 1));
  const [inputValue, setInputValue] = useState('');

  console.log('component', test); // после перерендера новое значение

  useEffect(() => {
    console.log('useEffect', test); // все ок, вызывается один раз, значение не меняется
  }, [test]);

  const handleInputChange = (e) => setInputValue(e.target.value);

  return <input type="text" onChange={handleInputChange} value={inputValue} />;
};


Where getRandomIntInRange is a simple function that gets a random number in the specified range.

const getRandomIntInRange = (min = 0, max = 0) => {
  const minNumber = Math.ceil(min);
  const maxNumber = Math.floor(max);

  return Math.floor(Math.random() * (maxNumber - minNumber + 1) + minNumber);
};


The problem is that I don't understand why when re-rendering a component, a new value appears in the normal console log ( console.log('component', test)) like:
component 5
...ввожу данные в инпут для перерендера компонента...
component 0
component 0


Those. the value seems to have changed, but the useEffect only fires once, and the value in it does not change. Example:
component 0
useEffect 3
...ввожу данные в инпут для перерендера компонента...
component 3
component 3


Please explain why this works

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexey, 2021-10-28
@IwanQ

This works because of StrictMode in React, because in this mode, at the development stage, React makes an additional check and makes calls to some methods twice (in fact, this is visible in the console):


Strict mode is not able to automatically detect side effects, but it helps to track them by making them more deterministic. This behavior is achieved by calling the following methods twice:
  1. The constructor, render, and shouldComponentUpdate methods of a class component
  2. GetDerivedStateFromProps class bean static method
  3. The body of a functional component
  4. Update functions (first argument to setState)
  5. Functions passed to useState, useMemo, or useReducer


Everything will be ok in the production assembly, you can check by removing the wrapper StrictMode , then in the body of the component and in useEffect the value of test will be the same and will be called only once when entering the input. console.log("component", test);

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question