Почему значение useRef динамически обновляется, когда оно является целым числом, но сохраняет предыдущее значение, когда оно является строкой?

#reactjs #use-ref

Вопрос:

Я только что изучил useRef и не понимаю, как это на самом деле работает. Например, #1

 function Ref() {
  const rerenderCount = useRef(0);

  useEffect(() => {
    rerenderCount.current = rerenderCount.current   1;
  });

  return <div>{rerenderCount.current}</div>;
}
 

Здесь useRef выдает тот же вывод, что и useState в следующем коде, #2

 function State() {
  const [rerenderCount, setRerenderCount] = useState(0);

  useEffect(() => {
    setRerenderCount(prevCount => prevCount   1);
  });

  return <div>{rerenderCount}</div>;
}
 

Но в этом коде #3 значение previousName.current всегда отображает предыдущее значение. Но он настроен на имя.

 const [name, setName] = useState("");
  const previousName = useRef(null);

  useEffect(() => {
    previousName.current = name;
  }, [name]);

  return (
    <div className="App">
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <div>
        My name is {name} and it used to be {previousName.current}
      </div>
    </div>
  );
 

Пожалуйста, кто-нибудь объясните, почему имя на один шаг назад, когда целое число обновляется вовремя. Кроме того, каково использование [name] в useEffect. Без него или без него я получаю тот же результат и подсчет.

Комментарии:

1. [name] в использовании эффект-это зависимость. Внутри этого массива вы объявляете список зависимостей, и когда хотя бы одна из них изменяется, выполняется код внутри useEffect. код также запускается при самой первой отрисовке. Таким образом, вы меняетесь previousName.current каждый раз, когда вводите что-то во входной текст. Если вы не добавите какую-либо зависимость useEffect , она будет запускаться каждый раз, когда компонент будет повторно отрисован.

2. @Antonio Может, пожалуйста, объяснить, почему perviousName.current всегда стоит на одну букву позади имени? например, когда я набираю «abcd» .. имя = «abcd», но имя.текущий = «abc»? Это внутри useEffect, поэтому, когда имя обновляется, почему useRef не обновляется?

Ответ №1:

В тебе пример previousName — один шаг позади, потому что при изменении name состояния компонента рендеринг, useEffect вызывается и previousName обновляется, но изменения не вызвать нового перевода (useRef не как useState, компонент не будет повторно визуализировать), поэтому вы видите name обновляется правильно, но previousName с тем же значением, как и раньше, даже если его значение изменилось. Это связано с тем, что изменение previousName происходит во время последующего рендеринга, вызванного изменением состояния. Чтобы увидеть его изменение, потребуется дополнительная визуализация. Чтобы избежать такого поведения, вы можете использовать обработчик событий и не полагаться на крючок useEffect.

 const handleChange = (text: string) => {
    setName(text);
    previousName.current = text;
  };

  return (
    <div className="App">
      <input value={name} onChange={(e) => handleChange(e.target.value)} />
      <div>
        My name is {name} and it used to be {previousName.current}
      </div>
    </div>
  );
 

Комментарии:

1. Теперь я понимаю, спасибо.

2. Если это приемлемо для вас и вы считаете, что это может быть полезно для других людей, пожалуйста, подумайте о том, чтобы принять это.