Использование нескольких setHook заставляет компонент рендериться более одного раза?

Если у меня много useState и одним нажатием кнопки я вызываю несколько setHook, рендерится ли он несколько раз или только один раз?

например

export default function setMultipleHooks() {

    const [hook1, setHook1] = useState(false)
    const [hook2, setHook2] = useState(false)
    const [hook3, setHook3] = useState(false)
    const [hook4, setHook4] = useState(false)

    const setHooks = () => {
        setHook1(true)
        setHook2(true)
        setHook3(true)
        setHook4(true)
    }

    return (
        <button onClick = {setHooks} >Hey</button>
    )

}

Когда я нажимаю кнопку, сколько раз она отображается? 1 или 4 раза?

Обычно, чтобы проверить, сколько раз рендерится компонент, я просто добавляю console.info в метод render, но с функциональными компонентами я не знаю, как это проверить.

Если он рендерится 4 раза, было бы лучше использовать только один useState (передача объекта), если 4 хука всегда связаны?

Возможный дубликат stackoverflow.com/questions/53048495/…

Shubham Khatri 09.04.2019 07:40
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
4
1
5 499
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

React может пакетировать несколько вызовов setState и отображать их все сразу. И в вашем случае это происходит, потому что вы находитесь внутри обработчика событий (onClick).

Он рендерится только один раз (начальный рендер не включен), как вы можете видеть из фрагмента ниже.

Проблема Github с пакетными вызовами setState() React

Тем не менее, вы можете использовать объект с 4 свойствами вместо 4 переменных состояния хуков. Но вам нужно быть осторожным при обновлении состояния, потому что setState() хука не объединяет ваше последнее состояние автоматически с вашим новым свойством состояния. Он полностью заменяет состояние новым объектом, который вы передаете.

React Docs — Использование хука состояния

Итак, вам нужно сделать что-то вроде этого:

function YourComponent() {
  const INITIAL_STATE = {a: false, b: false, c: false, d: false};
  const [state,setState] = useState(INITIAL_STATE);

  function handleClick() {
    setState((prevState) => {
      return({
        ...prevState,
        b: true
      });
    });
  }

}

const { useState, useRef, useEffect } = React;

function App() {

  const renderTimes = useRef(0);

  const [hook1, setHook1] = useState(false);
  const [hook2, setHook2] = useState(false);
  const [hook3, setHook3] = useState(false);
  const [hook4, setHook4] = useState(false);
  
  const setHooks = () => {
    setHook1(true);
    setHook2(true);
    setHook3(true);
    setHook4(true);
  }

  useEffect( () => {
    renderTimes.current+=1;
  });

  return (
    <div>
      <div>I rendered {renderTimes.current} time(s).</div>
      <div>NOTE: The initial render is not included.</div>
      <div>State hook1 is equal to: {hook1.toString()}</div>
      <div>State hook2 is equal to: {hook2.toString()}</div>
      <div>State hook3 is equal to: {hook3.toString()}</div>
      <div>State hook4 is equal to: {hook4.toString()}</div>
      <button onClick = {setHooks}>Click</button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id = "root"></div>

Я просто добавил useRef() для хранения счетчика рендеринга и useEffect() для увеличения счетчика рендеринга, так как он запускается после каждого рендера.

cbdeveloper 08.04.2019 16:00

Normally to check how many times the component is rendering, I just put a console.info in the render method, but with functional components, I'm not sure how to test this.

Просто поместите console.info внутрь функции (сама функция является render методом). Он будет отображаться только один раз, потому что существует небольшой интервал времени, в течение которого, если произойдет несколько вызовов установщика useState, их обновления будут пакетными.

If it renders 4 times, it would be better to use only one useState (passing an object) if the 4 hooks are always related?

Если у вас сложное состояние, вам действительно следует подумать useReducer.


Более:

https://stackoverflow.com/a/54716601/10995369

https://github.com/acdlite/react-fiber-архитектура

Другие вопросы по теме