Использование нескольких setHook делает рендеринг компонента более одного раза? - PullRequest
1 голос
/ 08 апреля 2019

Если у меня много 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.log в метод render, но с функциональными компонентами я не уверен, как это проверить.

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

Ответы [ 2 ]

1 голос
/ 08 апреля 2019

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

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

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

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


Подробнее:

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

https://github.com/acdlite/react-fiber-architecture

1 голос
/ 08 апреля 2019

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

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

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

Тем не менее можно использовать объект с 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>
...