Когда React выполняет рендеринг после вызова setState внутри обработчика события? - PullRequest
4 голосов
/ 27 сентября 2019

Из React DOCS:

https://reactjs.org/docs/state-and-lifecycle.html

Обновления состояний могут быть асинхронными

React может пакетировать несколько вызовов setState ()в одном обновлении для производительности.

Это имеет смысл.Если у вас есть что-то похожее на функцию ниже, было бы очень неэффективно повторять рендеринг при каждом setState вызове

const [state1,setState1] = useState(false);
const [state2,setState2] = useState(false);
const [state3,setState3] = useState(false);

function handleClick() {
  setState1(true);
  setState2(true);
  setState3(true);
}

Так что, в ситуации выше, я ожидаю, что React будет пакетировать все 3 setStateзвонки в один повторный рендер.И это именно так!

Но я хочу знать следующее:

После того, как handleClick завершено, гарантируется повторный рендер немедленно handleClick уже работает?Я имею в виду буквально сразу, как синхронно сразу?

Из этого фрагмента, который я построил, кажется, что это правда.Реагирует синхронно применяет обновления (повторной визуализации) после завершения handleClick.Поправьте меня, если я ошибаюсь, предполагая, что.

См. Фрагмент ниже:

  • Нажмите в 3 раза быстрее, чем вы можете
  • handleClick вызоветsetState и будет записывать текущее значение props.counter
  • На App есть дорогой цикл, поэтому потребуется много времени для повторного рендеринга
  • Вы сможетещелчок намного быстрее, чем React может перерисовать все приложение
  • Но вы увидите, что props.counter отличается каждый раз, без повторов, даже если вы нажимаете несколько раз очень быстро
  • Это означает, что после обработки вашего второго клика (это займет некоторое время из-за дорогого цикла), React уже заново отрендерил все это, и функция handleClick уже была воссоздана с новым значением для props.counter, котороепришел из обновленного состояния counter.
  • Попробуйте нажать 5 раз очень быстро, и вы увидите, что поведение такое же.

ВОПРОС

Когда setState вызовы выполняются внутри функции обработчика событий, сразуФункция обработчика завершила работу, гарантируется ли, что повторное отображение будет выполнено немедленно (синхронно) после этого завершения обработчика?

function App() {
  console.log("App rendering...");
  const [counter, setCounter] = React.useState(0);

  // AN EXPENSIVE LOOP TO SLOW DOWN THE RENDER OF 'App'
  
  for (let i = 0; i < 100000; ) {
    for (let j = 0; j < 10000; j++) {}
    i = i + 1;
  }

  return <Child counter={counter} setCounter={setCounter} />;
}

function Child(props) {
  console.log("Child rendering...");
  
  // THIS FUNCTION WILL CALL 'setState'
  // AND WILL ALSO LOG THE CURRENT 'props.counter'
  
  function handleClick() {
    props.setCounter(prevState => prevState + 1);
    console.log(props.counter);
  }

  return (
    <React.Fragment>
      <div>Counter: {props.counter}</div>
      <button onClick={handleClick}>Click</button>
    </React.Fragment>
  );
}

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

Ответы [ 2 ]

5 голосов
/ 27 сентября 2019

После завершения handleClick гарантируется ли повторный рендеринг немедленно handleClick завершил работу?Я имею в виду буквально сразу, как синхронно сразу

Для определенных событий, включая click, React гарантирует, что компонент будет перерисован до того, как произойдет другое событие.(Это не относится к другим событиям, таким как mousemove.) Вы можете найти, какие события какие здесь .Похоже, что нынешняя терминология такова: DiscreteEvent s - это те, для которых существует эта гарантия, а UserBlockingEvent s - те, для которых она не гарантирована.Вполне возможно, что в текущей реализации это означает, что это делается синхронно в конце обработки события… но я думаю, что гарантия менее конкретна, чем это.

Я узнал об этом от Дана Абрамова в Twitter (он использовал более старую терминологию для событий).


¹ Редактировать: и фактически, его ответ Джозеф Д. указывает на комментарийДан Абрамов говорит, что это пока что, но также говорит «Это детали реализации и могут измениться в будущих версиях» .

3 голосов
/ 27 сентября 2019

гарантируется ли, что повторное рендеринг произойдет немедленно (синхронно) после завершения работы обработчика?

Да для onClick.

Как указывает Дэн Абрамов :

React пакетирует все setStates, выполненные во время обработчика событий React, и применяет их непосредственно перед выходом из своего собственного обработчика событий браузера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...