Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translation of reconciliation #152

Merged
merged 4 commits into from
Feb 15, 2019
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 45 additions & 45 deletions content/docs/reconciliation.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
---
id: reconciliation
title: Reconciliation
title: Reconciliación
permalink: docs/reconciliation.html
---

React provides a declarative API so that you don't have to worry about exactly what changes on every update. This makes writing applications a lot easier, but it might not be obvious how this is implemented within React. This article explains the choices we made in React's "diffing" algorithm so that component updates are predictable while being fast enough for high-performance apps.
React proporciona una API declarativa para que no tengas que preocuparte por qué es exactamente lo que cambia en cada actualización. Esto facilita mucho la escritura de aplicaciones, pero podría no ser obvio cómo se implementa esto dentro de React. Este artículo explica las elecciones que hicimos en el algoritmo "diferencial" de React para que las actualizaciones de los componentes sean predecibles y al mismo tiempo sean lo suficiente rápidas para las aplicaciones de alto rendimiento.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

## Motivation {#motivation}
## Motivacion {#motivation}
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

When you use React, at a single point in time you can think of the `render()` function as creating a tree of React elements. On the next state or props update, that `render()` function will return a different tree of React elements. React then needs to figure out how to efficiently update the UI to match the most recent tree.
Cuando usas react, en un momento dado puedes pensar que la función `render()` crea un árbol de elementos de React. En la siguiente actualización de estado o propiedades, esa función `render()` devolverá un árbol diferente de elementos de React. React luego debe descubrir cómo actualizar de manera eficiente la interfaz de usuario para que coincida con el árbol más reciente.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

There are some generic solutions to this algorithmic problem of generating the minimum number of operations to transform one tree into another. However, the [state of the art algorithms](http://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf) have a complexity in the order of O(n<sup>3</sup>) where n is the number of elements in the tree.
Existen algunas soluciones genéricas para este problema algorítmico de generar el número mínimo de operaciones para transformar un árbol en otro. Sin embargo, los [state of the art algorithms](http://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf) tienen una complejidad en el orden de O(n<sup>3</sup>) donde n es el número de elementos en el árbol.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

If we used this in React, displaying 1000 elements would require in the order of one billion comparisons. This is far too expensive. Instead, React implements a heuristic O(n) algorithm based on two assumptions:
Si utilizamos esto en React, mostrar 1000 elementos requeriría del orden de mil millones de comparaciones. Esto seria demasiado costoso. En su lugar, React implementa un algoritmo heurístico O(n) basado en dos suposiciones.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

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.
1. Dos elementos de diferentes tipos producirán diferentes árboles.
2. El desarrollador puede insinuar qué elementos secundarios pueden ser estables en diferentes renders con una propiedad `key`.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

In practice, these assumptions are valid for almost all practical use cases.
En la práctica, estos supuestos son válidos para casi todos los casos de uso práctico.

## The Diffing Algorithm {#the-diffing-algorithm}
## El algoritmo de diferencia {#the-diffing-algorithm}
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

When diffing two trees, React first compares the two root elements. The behavior is different depending on the types of the root elements.
Al diferenciar dos árboles, React primero compara dos elementos raíz. El comportamiento es diferente dependiendo de los tipos de elementos raíz.

### Elements Of Different Types {#elements-of-different-types}
### Elementos de diferentes tipos {#elements-of-different-types}

Whenever the root elements have different types, React will tear down the old tree and build the new tree from scratch. Going from `<a>` to `<img>`, or from `<Article>` to `<Comment>`, or from `<Button>` to `<div>` - any of those will lead to a full rebuild.
Cada vez que los elementos raíz tienen diferentes tipos, React derribará el árbol viejo y construirá el nuevo árbol desde cero. Pasando de `<a>` a `<img>`, o de `<Article>` a `<Comment>`, o de `<Button>` a `<div>` - cualquiera de esos conducirá a una reconstrucción completa.

When tearing down a tree, old DOM nodes are destroyed. Component instances receive `componentWillUnmount()`. When building up a new tree, new DOM nodes are inserted into the DOM. Component instances receive `componentWillMount()` and then `componentDidMount()`. Any state associated with the old tree is lost.
Al derribar un árbol, los nodos antiguos del DOM se destruyen. Las instacias de los componentes reciben `componentWillUnmount()`. Al construir un nuevo árbol, los nuevos elementos del DOM se insertan. Las instancias de componentes reciben `componentWillMount()` y luego `componentDidMount()`. Cualquier estado asociado al árbol viejo se pierde.

Any components below the root will also get unmounted and have their state destroyed. For example, when diffing:
Cualquier componente debajo de la raíz también se desmontará y se destruira su estado. Por ejemplo, cuando difiere:
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

```xml
<div>
Expand All @@ -41,43 +41,43 @@ Any components below the root will also get unmounted and have their state destr
</span>
```

This will destroy the old `Counter` and remount a new one.
Esto destruira el `Counter` viejo y volvera a montar uno nuevo.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

### DOM Elements Of The Same Type {#dom-elements-of-the-same-type}
### Elementos del DOM del mismo tipo {#dom-elements-of-the-same-type}

When comparing two React DOM elements of the same type, React looks at the attributes of both, keeps the same underlying DOM node, and only updates the changed attributes. For example:
Al comparar dos elementos elementos React DOM del mismo tipo, React analiza los atributos de ambos, mantiene el mismo nodo DOM subyacente, y solo actualiza los atributos modificados. Por ejemplo:

```xml
<div className="before" title="stuff" />

<div className="after" title="stuff" />
```

By comparing these two elements, React knows to only modify the `className` on the underlying DOM node.
Comparando estos dos elementos, React sabe que solo debe modificar el `className` en el nodo DOM subyacente.

When updating `style`, React also knows to update only the properties that changed. For example:
Al actualizar `style`, React también sabe actualizar solo las propiedades que cambiaron. Por ejemplo:

```xml
<div style={{color: 'red', fontWeight: 'bold'}} />

<div style={{color: 'green', fontWeight: 'bold'}} />
```

When converting between these two elements, React knows to only modify the `color` style, not the `fontWeight`.
Al convertir entre estos dos elementos, React sabe que solo debe modificar el estilo `color`, no el `fontWeight`.

After handling the DOM node, React then recurses on the children.
Después de manejar el nodo DOM, React recurre a los hijos.

### Component Elements Of The Same Type {#component-elements-of-the-same-type}
### Componentes del mismo tipo {#component-elements-of-the-same-type}

When a component updates, the instance stays the same, so that state is maintained across renders. React updates the props of the underlying component instance to match the new element, and calls `componentWillReceiveProps()` and `componentWillUpdate()` on the underlying instance.
Cuando se actualiza un componente, la instancia permanece igual, por lo que el estado se mantiene en todas las representaciones. React actualiza las propiedades de la instancia del componente subyacente para que coincida con el nuevo elemento, y llama a `componentWillReceiveProps()` y `componentWillUpdate()` en la instancia subyacente.

Next, the `render()` method is called and the diff algorithm recurses on the previous result and the new result.
A continuación, se llama al método `render()` y al algoritmo de diferenciación en el resultado anterior y el nuevo resultado.

### Recursing On Children {#recursing-on-children}
### Recursión en hijos {#recursing-on-children}

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.
De forma predeterminada, cuando hay recursión en los hijos de un nodo DOM, React simplemente itera sobre ambas listas de hijos al mismo tiempo y genera una mutación siempre que haya diferencia.

For example, when adding an element at the end of the children, converting between these two trees works well:
Por ejemplo, al agregar un elemento al final de los hijos, la conversión entre estos dos árboles funciona bien:

```xml
<ul>
Expand All @@ -92,9 +92,9 @@ For example, when adding an element at the end of the children, converting betwe
</ul>
```

React will match the two `<li>first</li>` trees, match the two `<li>second</li>` trees, and then insert the `<li>third</li>` tree.
React coincidira con los árboles `<li>first</li>`, con los dos árboles `<li>second</li>` y luego insertara el árbol `<li>third</li>`.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

If you implement it naively, inserting an element at the beginning has worse performance. For example, converting between these two trees works poorly:
Si lo implementas ingenuamente, la inserción de un elemento al principio tiene un peor rendimiento. Por ejemplo, la conversión entre estos dos árboles funcionaria mal:
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

```xml
<ul>
Expand All @@ -109,11 +109,11 @@ If you implement it naively, inserting an element at the beginning has worse per
</ul>
```

React will mutate every child instead of realizing it can keep the `<li>Duke</li>` and `<li>Villanova</li>` subtrees intact. This inefficiency can be a problem.
React mutará a cada hijo en lugar de darse cuenta que puede mantener intactos los subárboles `<li>Duke</li>` y `<li>Villanova</li>`. Esta ineficiencia puede ser un problema.

### Keys {#keys}
### Claves {#keys}
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

In order to solve this issue, React supports a `key` attribute. When children have keys, React uses the key to match children in the original tree with children in the subsequent tree. For example, adding a `key` to our inefficient example above can make the tree conversion efficient:
Para resolver este problema, React soporta el atributo `key`. Cuando los hijos tienen claves, React lo usa para relacionar los hijos del árbol original con los hijos del árbol posterior. Por ejemplo, agregando una clave a nuestro ejemplo anterior puede hacer que la conversión de árbol sea eficiente:
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

```xml
<ul>
Expand All @@ -128,30 +128,30 @@ In order to solve this issue, React supports a `key` attribute. When children ha
</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.
Ahora, React sabe que el elemento con la clave `'2014'` es nuevo, y los elementos con la clave `'2015'` y `'2016'` se acaban de mover.

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:
En la practica, encontrar una clave no suele ser difícil. Es posible que el elemento que va a mostrar ya tenga un ID único, por lo que la clave puede provenir de sus datos:
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

```js
<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.
Cuando ese no sea el caso, puede agregar una nueva propiedad de ID a su modelo o marcar algunas partes del contenido para generar una clave. La clave solo tiene que ser única entre sus hermanos, no globalmente única.

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.
Como último recurso, puede pasar el índice de un elemento en la matriz como una clave. Esto puede funcionar bien si los items nunca se reordenan, pero los reordenamientos serán lentos.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

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.
Reorganizar también puede causar problemas de estado del componente cuando los índices se utilizan como claves. Si la clave es un índice, mover un elemento lo cambia. Como resultado, el estado el componente para cosas como entradas no controladas pueden mezclarse y actualizarse de manera inesperada.

[Here](codepen://reconciliation/index-used-as-key) is an example of the issues that can be caused by using indexes as keys on CodePen, and [here](codepen://reconciliation/no-index-used-as-key) is an updated version of the same example showing how not using indexes as keys will fix these reordering, sorting, and prepending issues.
[Aquí](codepen://reconciliation/index-used-as-key) es un ejemplo de los problemas que pueden ser causados por el uso de índices como claves en Codepen, y [aquí](codepen://reconciliation/no-index-used-as-key) es una versión actualizada del mismo ejemplo que muestra cómo no usar los índices como claves solucionará estos problemas de reordenación, clasificación y preparación.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

## Tradeoffs {#tradeoffs}
## Compensaciones {#tradeoffs}

It is important to remember that the reconciliation algorithm is an implementation detail. React could rerender the whole app on every action; the end result would be the same. Just to be clear, rerender in this context means calling `render` for all components, it doesn't mean React will unmount and remount them. It will only apply the differences following the rules stated in the previous sections.
Es importante recordar que el algoritmo de reconciliación es un detalle de la implementación. React podría re-pintar toda la aplicación en cada acción; El resultado final sería el mismo. Para que quede claro, re-pintar en este contexto significa llamar a `render` para todos los componentes, no significa que React los desmonte y los vuelva a montar. Solo aplicará las diferencias siguiendo las reglas establecidad en las secciones anteriores.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

We are regularly refining the heuristics in order to make common use cases faster. In the current implementation, you can express the fact that a subtree has been moved amongst its siblings, but you cannot tell that it has moved somewhere else. The algorithm will rerender that full subtree.
Regularmente refinamos las herísticas para que los casos de uso común sean más rápidos. En la implementación actual, puede expresar el hecho de que un subárbol se ha movido entre sus hermanos, pero no puede decir que se haya movido a otro lugar. El algoritmo reenviará ese subárbol completo.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved

Because React relies on heuristics, if the assumptions behind them are not met, performance will suffer.
Debido a que React se basa en heurísticas, si no se cumplen las suposiciones detrás de ellas, el rendimiento se verá afectado.

1. The algorithm will not try to match subtrees of different component types. If you see yourself alternating between two component types with very similar output, you may want to make it the same type. In practice, we haven't found this to be an issue.
1. El algoritmo no intentará hacer coincidir subárboles de diferentes tipos de componentes. Si te ves alternando entre dos tipos de componentes muy similares, es posible que quieras hacerlo del mismo tipo. En la práctica, no hemos encontrado que esto sea un problema.

2. Keys should be stable, predictable, and unique. Unstable keys (like those produced by `Math.random()`) will cause many component instances and DOM nodes to be unnecessarily recreated, which can cause performance degradation and lost state in child components.
2. Las claves deben ser estables, predecibles y únicas. Las claves inestables (como las producidas por `Math.random()`) harán que muchas instancias de componentes y nodos del DOM se vuelvan a crear innecesariamente, lo que puede causar una degradación del rendimiento y un estado perdido en componentes secundarios.
devrchancay marked this conversation as resolved.
Show resolved Hide resolved