React рендерит все компоненты и подкомпоненты каждый раз, когда setState
вызывается?
Если так, то почему? Я думал, что идея была в том, что React рендерится так мало, как нужно - когда состояние меняется.
В следующем простом примере оба класса визуализируются снова при нажатии на текст, несмотря на тот факт, что состояние не изменяется при последующих щелчках, поскольку обработчик onClick всегда устанавливает state
одинаковое значение:
this.setState({'test':'me'});
Я бы ожидал, что рендеринг будет происходить только в случае изменения state
данных.
Вот код примера, как JS Fiddle и встроенный фрагмент:
var TimeInChild = React.createClass({
render: function() {
var t = new Date().getTime();
return (
<p>Time in child:{t}</p>
);
}
});
var Main = React.createClass({
onTest: function() {
this.setState({'test':'me'});
},
render: function() {
var currentTime = new Date().getTime();
return (
<div onClick={this.onTest}>
<p>Time in main:{currentTime}</p>
<p>Click me to update time</p>
<TimeInChild/>
</div>
);
}
});
ReactDOM.render(<Main/>, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>
[1]: http://jsfiddle.net/fp2tncmb/2/
javascript
reactjs
Брэд Паркс
источник
источник
setState()
даже с фиктивными данными заставляет элемент отображаться по-другому, поэтому я бы сказал да. Абсолютно следует попытаться перерисовать ваш объект, когда что-то могло измениться, потому что в противном случае ваша демонстрация - при условии, что это было предполагаемое поведение - не сработала бы!shouldComponentUpdate
метод, который, как я предполагал, должна быть уже включена в простую версию React. Похоже, версия по умолчанию, включенная в реагирование, просто возвращает,true
что заставляет компонент каждый раз перерисовываться.Ответы:
По умолчанию - да.
Существует метод boolean shouldComponentUpdate (объект nextProps, объект nextState) , у каждого компонента есть этот метод, и он отвечает за определение "следует ли обновить компонент (запустить функцию рендеринга )?" каждый раз, когда вы меняете состояние или передаете новый реквизит из родительского компонента.
Вы можете написать свою собственную реализацию метода shouldComponentUpdate для своего компонента, но реализация по умолчанию всегда возвращает true - это означает, что функция рендеринга всегда перезапускается.
Цитата из официальных документов http://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate
Следующая часть вашего вопроса:
Есть два этапа того, что мы можем назвать «рендерингом»:
Виртуальный рендеринг DOM: при вызове метода рендеринга возвращается новая виртуальная структура DOM компонента. Как я упоминал ранее, этот метод рендеринга вызывается всегда, когда вы вызываете setState () , потому что shouldComponentUpdate всегда возвращает true по умолчанию. Таким образом, по умолчанию, здесь нет оптимизации в React.
Нативная визуализация DOM: React изменяет реальные DOM-узлы в вашем браузере, только если они были изменены в Virtual DOM и настолько мало, насколько это необходимо - это та замечательная функция React, которая оптимизирует реальную мутацию DOM и делает React быстрой.
источник
setState
если вы обнаружите разницу? Если так, как это сделать лучше всего - сравнить строки json, построить и сравнить хеши объектов, ...?Нет, React не рендерит все, когда состояние меняется.
Всякий раз, когда компонент загрязнен (его состояние изменилось), этот компонент и его дочерние элементы повторно отображаются. Это, в некоторой степени, заключается в повторной визуализации как можно меньше. Единственный раз, когда рендер не вызывается, это когда какая-то ветка перемещается в другой корень, где теоретически нам не нужно ничего рендерить. В вашем примере
TimeInChild
это дочерний компонентMain
, поэтому он также перерисовывается при изменении состоянияMain
.React не сравнивает данные о состоянии. Когда
setState
вызывается, он помечает компонент как грязный (что означает, что он должен быть повторно обработан). Важно отметить, что хотяrender
метод компонента вызывается, реальный DOM обновляется только в том случае, если выходные данные отличаются от текущего дерева DOM (иначе говоря, различие между деревом Virtual DOM и деревом DOM документа). В вашем примере, хотяstate
данные не изменились, время последнего изменения изменилось, что сделало Virtual DOM отличным от DOM документа, поэтому HTML-код обновляется.источник
render()
метод был «чистым» - независимым от внешнего состояния.some branch is moved to another root
? Что ты называешьbranch
? Что ты называешьroot
?what does it mean some branch is moved to another root? What do you call branch? What do you call root?
Хотя это указано во многих других ответах здесь, компонент должен либо:
реализовать
shouldComponentUpdate
для визуализации только при изменении состояния или свойствпереключиться на расширение PureComponent , который уже реализует
shouldComponentUpdate
метод внутри для поверхностных сравнений.Вот пример, который использует
shouldComponentUpdate
, который работает только для этого простого случая использования и демонстрационных целей. Когда это используется, компонент больше не перерисовывается при каждом щелчке, а отображается при первом отображении и после однократного нажатия.источник
Да. Он вызывает метод render () каждый раз, когда мы вызываем setState, а когда «shouldComponentUpdate» возвращает false.
источник
Другой причиной «потерянного обновления» может быть следующая:
Если это проблема, то вы можете избежать установки состояния во время обновления, вы должны проверить значение параметра состояния, как это
Другое решение - добавить инициализированное свойство к состоянию и установить его в первый раз (если состояние инициализируется ненулевым значением).
источник
Не все компоненты.
state
в компоненте выглядит как источник водопада состояние всей APP.Таким образом, изменение происходит с того места, где вызывается setState. Тогда дерево
renders
будет вызвано оттуда. Если вы использовали чистый компонент,render
он будет пропущен.источник