La mayoría de las personas que trabajan en la interfaz, de una forma u otra, se encontraron con una reacción. Esta es una biblioteca de JavaScript que ayuda a crear interfaces geniales; en los últimos años ha ganado una gran popularidad. Sin embargo, no mucha gente sabe cómo funciona por dentro.
En esta serie de artículos, leemos el código y tratamos de averiguar de qué son responsables los paquetes que se encuentran debajo del capó para la reacción, para qué se usan y cómo funcionan. Los más básicos que utilizamos en el navegador son react
, react-dom
, events
y react-reconciler
.
Nos moveremos en orden y hoy tenemos un artículo sobre el paquete de react
. A quién le importa lo que hay en este paquete: ve debajo del gato.
En primer lugar, haremos un pequeño ejemplo, en base al cual consideraremos este paquete. Nuestro gadget se verá así:
function App() { const [text, changeText] = React.useState('Initial'); return ( <div className="app"> <span>{text}</span> <input type="text" value={text} onInput={(e) => changeText(e.target.value)} /> </div> ); } ReactDOM.render( <App />, document.getElementById('root') ) ;
Echemos un vistazo rápido a este código. Aquí vemos la llamada del gancho a través de React.useState('Initial')
, un poco de JSX y la llamada del método de renderizado para obtener todo esto en la página.
De hecho, como mucha gente sabe, este no es el código final que procesa el navegador. Antes de que se ejecute, se transpila, por ejemplo, con una babel. En este caso, lo que devuelve la función se convertirá en lo siguiente:
return React.createElement( "div", { className: "app" }, React.createElement("span", null, text), React.createElement("input", { type: "text", value: text, onInput: function onInput(e) { return changeText(e.target.value); } }) );
¿A quién le importa experimentar y ver en qué se convierte su código de babel ?
React.createElement
Entonces, recibimos muchas llamadas a React.createElement()
y tiempo para ver qué hace esta función. Lo describiremos en palabras (o también puede mirar el archivo - ReactElement.js ).
En primer lugar, verifica si tenemos accesorios (en el código, el objeto con los accesorios que pasamos se llama config
).
A continuación, verificamos si tenemos accesorios key
y de ref
que no están undefined
, y los guardamos, si los hay.
if (hasValidKey(config)) { key = '' + config.key; }
Un punto interesante es que config.key
se config.key
en una cadena, lo que significa que puede pasar cualquier tipo de datos como clave, lo principal es que implementa el .toString()
o .valueOf()
y devuelve un valor único para un conjunto particular.
Los siguientes son los siguientes pasos:
- copie los accesorios que se pasaron al elemento;
- agregue el campo
children
allí si los pasamos no con accesorios, sino como un elemento anidado; - establecemos valores predeterminados de
defaultProps
para aquellas propiedades que no definimos anteriormente.
Cuando hemos preparado todos los datos, llamamos a una función interna que crea un objeto que describe nuestro componente. Este objeto se ve así:
{ // This tag allows us to uniquely identify this as a React Element $$typeof: REACT_ELEMENT_TYPE, // Symbol // Built-in properties that belong on the element type: type, key: key, ref: ref, props: props, // Record the component responsible for creating this element. _owner: owner, }
Aquí tenemos la propiedad $$typeof
, que es un símbolo, por lo tanto, deslice de todos modos qué objeto fallará.
La propiedad type
almacena el tipo del elemento a crear. En el caso de nuestro ejemplo, esta será la función App()
y las líneas 'div'
, 'span'
y 'input'
.
La propiedad de la key
contendrá la misma clave, por lo que las advertencias vuelan a la consola.
Los accesorios contendrán lo que pasamos, children
y lo que se especificó en defaultProps
. La propiedad _owner
necesaria para un trabajo correcto con ref
.
Traducido a nuestro ejemplo, el resultado de React.createElement(App, null)
verá así:
{ $$typeof: REACT_ELEMENT_TYPE, type: App, key: null, ref: null, props: {}, _owner: null, }
Además, en el modo de desarrollo, tendremos un campo adicional que se usará para mostrar una hermosa pila con el nombre y la línea del archivo:
_source: { fileName: "/Users/appleseed/react-example/src/index.js", lineNumber: 7 }

Para resumir un poco de lo que vimos arriba. El paquete de react
actúa como un traductor entre nosotros y otros paquetes que funcionan aún más en nuestra aplicación, traduciendo nuestras llamadas en palabras que son comprensibles, por ejemplo, para el reconciliador.
React.useState
En la versión 16.8, aparecieron ganchos. Qué es y cómo usarlo puede leer el enlace , pero ahora echamos un vistazo a lo que se encuentra en el paquete de react
.
De hecho, no hay mucho que decir. En esencia, un paquete es una fachada a través de la cual nuestros desafíos se dirigen a entidades internas.
Entonces, useState
no es más que dos líneas de código:
export function useState<S>(initialState: (() => S) | S) { const dispatcher = resolveDispatcher(); return dispatcher.useState(initialState); }
Los ganchos restantes se ven casi idénticos. Aquí obtenemos el despachador actual, que es un objeto y contiene campos, por ejemplo useState
. Este despachador cambia dependiendo de si tenemos el primer render ahora o si solo queremos actualizar el componente.
La implementación real de los ganchos se almacena en el paquete react-reconciler
, del que hablaremos en uno de los siguientes artículos.
Que sigue
Una cosa mas. Después de leer este artículo, puede comprender por qué siempre importamos el paquete de reacción, incluso si no lo usamos directamente. Esto es necesario para que después de digerir nuestro jsx por la burbuja, tengamos una variable React
.
Los chicos del equipo de reacción se encargaron de esto (y no solo de esto) y ahora están trabajando para reemplazar createElement
.
Tratando de explicar en pocas palabras: existe el deseo de reemplazar el método actual de creación de elementos con dos: jsx
y jsxs
. Esto es necesario por varias razones:
- discutimos anteriormente cómo funciona
createElement
. Constantemente copia accesorios y agrega el campo children
al objeto, en el que guarda los hijos que pasamos como argumentos a la función (3 argumentos y más). Ahora se propone hacer esto en la etapa de convertir jsx
a llamadas javascript
, porque crear un elemento es a menudo una función llamada y no es libre de realizar modificaciones de accesorios en tiempo de ejecución cada vez; - puede deshacerse de importar el objeto
React
e importar solo funciones específicas ( import { jsx } from 'react'
, por ejemplo) y, en consecuencia, no puede agregar al ensamblado lo que no estamos utilizando. Además, no tiene que resolver el campo createElement
del objeto React
cada vez, porque tampoco es gratuito; - Discutimos anteriormente que tenemos un caso especial cuando sacamos la
key
de los accesorios y la reenviamos más. Ahora se propone tomar la key
de jsx
en la etapa de transpilación y pasarle el tercer parámetro a la función de creación de elementos.
Lee más aquí . El paquete de react
ya tiene jsxs
jsx
y jsxs
. Si desea jugar con esto, puede clonar el repositorio de reacción, establezca el indicador enableJSXTransformAPI
en true
en el archivo ReactFeatureFlags.js
del paquete shared
y compile su versión de la reacción ( yarn build
) con la nueva API habilitada.
Final
Con esto terminaré la historia de hoy sobre el paquete react
y la próxima vez hablaremos sobre cómo el paquete react-dom
usa lo que react
crea, qué métodos y cómo se implementa.
¡Gracias por leer hasta el final!