Reconciliation

  • 새로운 state, props를 받을 시, 새로운 react element tree를 생성하기위해 2가지 가정을한다.
  1. Two elements of different types will produce different trees
  2. The developer can hint at which child elements may be stable across different renders with a key prop

The Diffing Algorithm

When diffing two trees, React first compares the two root elements. The behavior is different depending on the types of the root elements.

Dom Elements Of The Same Type

  • React는 내부적으로 virtual DOM tree를 가지고 이를 actual Dom tree와 비교한다.
  • 만약 root elements가 다르다면, 새로운 tree를 만든다.
    • 그리고 이전의 dom node는 없어진다.
    • 그리고 root level밑에 있는 모든 자식 domponent들은 componentWillUnmount()를 수신한다.
  • new tree의 components들은 componentWillMount()와 componentDidMount()를 수신한다.
  • dom노드가 없어지고 새로 만들어지기때문에 기존dom 노드와 state도없어진다.
<div>
  <Counter />
</div>

// <div> -> <span> 으로 수정하면, root element가 다르기 때문에, dom tree는 완전히 없어졌다가 다시 만들어진다.
<span>
  <Counter />
</span>

그렇다면 같은 타입의 Dom Elements라면?

  1. 같은 타입의 React Dom Elements를 비교하게 된다면, React는 attribute를 확인한다.
  2. 그리고 Dom node는 유지하고 attribute만 update해준다.
// before
<div className="before" title="stuff" />
// after
<div className="after" title="stuff" />
  • 두 Elements를 비교하고 React는 className만 update해준다.

Style이 update된다면?

  • React는 update된 properties만 수정해준다.
<div style={{color: 'red', fontWeight: 'bold'}} />

<div style={{color: 'green', fontWeight: 'bold'}} />
  • 이경우 color값만 수정되고, fontWeight는 수정되지않는다.

  • 해당 DOM을 위와같이 처리한후, 자식에도 재귀적으로 처리한다.

    • After handling the DOM node, React then recurses on the children.

Component Elements Of The Same Type

  • Component가 update되면 state를 유지하기 위해서 동일한 instance를 유지한다.
  • React는 새로운 element에 match하기 위해서 컴포넌트 인스턴스안의 prop를 update한다. 그리고, 그 인스턴스의 componentWillReceiveProps()componentWillUpdate()가 불려진다.
  • 그다음 render()가 불려지고, 이전 결과와 새로운 결과에 대해서 the diff algorithme이 재귀적으로 불려진다.

Recursing On Children

  • DOM 노드의 children에 대해 반복 할 때 React는 동시에 두 childrens을 반복 실행하고 차이가있을 때마다 변형을 생성한다.
    • By default, when recursing on the children of a DOM node, React just iterates over both lists of children at the same time and generates a mutation whenever there’s a difference.
<ul>
  <li>first</li>
  <li>second</li>
</ul>

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>
  • 먼저 두개의 <li>first<li>trees를 비교하고, <li>second</li>trees를 비교하고, <li>third</li>tree를 추가한다.
  • 그래서 첫번째에 요소를 추가하면 성능이 떨어진다.
<ul>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

<ul>
  <li>Connecticut</li>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

Keys

  • 위와 같은 문제를 해결하기위해서 Key attribute를 제공한다.
  • React uses the key to match children in the original tree with children in the subsequent tree. For
<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

Now React knows that the element with key '2014' is the new one, and the elements with the keys '2015' and '2016' have just moved.

In practice, finding a key is usually not hard. The element you are going to display may already have a unique ID, so the key can just come from your data:

<li key={item.id}>{item.name}</li>

When that’s not the case, you can add a new ID property to your model or hash some parts of the content to generate a key. The key only has to be unique among its siblings, not globally unique.

As a last resort, you can pass an item’s index in the array as a key. This can work well if the items are never reordered, but reorders will be slow.

Reorders can also cause issues with component state when indexes are used as keys. Component instances are updated and reused based on their key. If the key is an index, moving an item changes it. As a result, component state for things like uncontrolled inputs can get mixed up and updated in unexpected ways.

Here is an example of the issues that can be caused by using indexes as keys on CodePen, and here is a updated version of the same example showing how not using indexes as keys will fix these reordering, sorting, and prepending issues.



https://reactjs.org/docs/reconciliation.html


'Front-End > React' 카테고리의 다른 글

React Component lifecycle  (0) 2018.11.20
Immutable.js  (0) 2018.09.14
Container components and Presentational components  (0) 2018.09.14
[React] HOC  (0) 2018.08.02

+ Recent posts