Feliz: [<reactcomponent>] vs React.functionComponent en React actualizar</reactcomponent>

Creado en 25 nov. 2020  ·  10Comentarios  ·  Fuente: Zaid-Ajaj/Feliz

Hola amigo,

Como ingenuo aspirante a desarrollador de frontend, tuve un comportamiento interesante:

Según sus documentos, prefiero usar React.functionComponent para crear componentes porque también puedo especificar el nombre del componente para una mejor depuración. Lo gracioso viene con react refresh.

Un código como este siempre activa la recarga de la página completa al realizar cualquier cambio en el código:

let subView = React.functionComponent("SubView", fun () ->
    Html.text "Hello from sub"
)

let topView = React.functionComponent("TopView", fun () ->
    Html.div [ Html.div "Hello from top"; subView () ]
)

image

Pero tener un componente raíz con [<ReactComponent>] hará que todas las actualizaciones funcionen bien sin realizar una actualización completa.

let subView = React.functionComponent("SubView", fun () ->
    Html.text "Hello from sub"
)

[<ReactComponent>]
let topView () = Html.div [ Html.div "Hello from top"; subView () ]

¿Es un error? ¿Es un error en la característica también conocida de elegante corbata negra? ¿Es todo culpa mía porque no obtengo la diferencia entre el atributo ReactComponent y la función React.functionComponent? 😄

Gracias por cualquier tipo de ayuda para comprender mejor.

question

Comentario más útil

¡Guau! ¡Simplemente guau! La persona tonta hace una pregunta estúpida y el chico inteligente responde con tres hojas A4 llenas de información y explicaciones relevantes. 🤯 ¡Simplemente rockeas, hombre! ¡Muchas gracias! ❤️ Ahora lo entiendo y comenzaré a usar Attribute en su lugar.

¿Todavía se recomienda nombrar los componentes de alguna manera (como lo hicimos usando el primer parámetro de React.functionComponent ) o esto ya no es necesario para el enfoque de atributos?

Todos 10 comentarios

El atributo será el camino a seguir en el futuro y es necesario para que reactive-refresh funcione. Al menos, así fue, pero pensé que @ Zaid-Ajaj resolvió eso para que no hubiera diferencia.

Hola Roman,

Esta es una muy buena pregunta para la que no hay una respuesta corta, aquí vamos.

Aunque una vez que solucione mis problemas de Internet en casa, reanudaré la transmisión nuevamente donde explico esto con detalles insoportables 😁

Según sus documentos, prefiero usar React.functionComponent para crear componentes porque también puedo especificar el nombre del componente para una mejor depuración. Lo gracioso viene con react refresh.

En primer lugar, quiero señalar que la documentación se encuentra en un estado de transición desafortunado: básicamente desactualizado con el último Feliz y [<ReactComponent>] bondad hasta que solucionemos los problemas del complemento del compilador y estabilicemos el AST utilizado por Fable . Lo que estoy tratando de decir es que los documentos no favorecen a React.functionComponent y si estás usando Fable 3, deberías comenzar a usar [<ReactComponent>] lugar.

Esto tiene que ver con cómo se genera el código Javascript. Ahora considere esta pieza de código de React:

const App = ({ title }) => {
  return (
    <h1>{title}</h1>
  )
};

<App title="My React Application" />

Este JS (que en realidad es JSX) desugars hasta el siguiente código JS

import { createElement } from 'react'

const App = ({ title }) => {
  return createElement("h1", null, title);
};

// <App /> compiles to a call to createElement
createElement(App, { title: "My React Application" })

Es muy importante notar que la inicialización del componente App través de <App ... /> se compila en una llamada a createElement desde JS.

Es importante por dos cosas:

  • Separa la definición del componente de su creación.
  • Permite que App sea ​​un valor estático (la identidad está reservada y React hace uso de ella)

Ahora, la forma en que se implementa React.functionComponent es "mala" para React porque combina la definición y la creación de una sola vez. Este código F #

let app React.functionComponent("App", fun (props: {|  tite: string |}) -> Html.h1 props.title)

Es una especie de equivalente a decir

let app = 
  let render(props: {|  tite: string |}) = 
    let renderFn props= Html.h1 props.title
    createElement(renderFn , props)
  render.displayName <- "App"
  render

Ahora esto es "malo" porque createElement representa un componente que se define dinámicamente en cada invocación y muta el displayName de la función en lugar de usar el nombre de la función en sí.

Este azúcar de sintaxis que emplea el React.functionComponent no afecta el comportamiento en tiempo de ejecución de React y es por eso que podemos usarlo sin problemas para construir la aplicación React. Los problemas comienzan a surgir cuando las HERRAMIENTAS alrededor de las aplicaciones React comienzan a analizar el código generado: webpack, babel, react-refresh son todas herramientas que buscan el código generado, inyectan algo de magia aquí y allá para hacer posible el reemplazo del módulo en caliente, pero con React.functionComponent no es posible porque el código generado no se ajusta a cómo se construyen normalmente las aplicaciones de React cuando se escribe JS y muchas de las herramientas de React hacen suposiciones basadas en el hecho de que el código está escrito de acuerdo con el estándar Reaccione eso que generado por una herramienta.

La solución a estos problemas viene en Fable 3, donde se nos permite personalizar la compilación del código a través de complementos del compilador. Si consideras este código F # Feliz en Fable 3

[<ReactComponent>]
let app (title: string) = Html.h1 title 

app "My  React Application"

Luego se compila al equivalente de este JS (no es exacto porque hay más magia)

const App = (props) { 
   const title = props.title
   return createElement("h1", null, title)
}

createElement(App, { title: "My  React Application" })

Ahora, este código generado está personalizado para que se parezca a lo que esperan las herramientas de React:

  • Las definiciones y creaciones de los componentes de la función están separadas
  • Los componentes se definen en mayúsculas (sí, esto también es obligatorio y el complemento del compilador reescribe automáticamente la definición)
  • Los parámetros de entrada se traducen automáticamente en accesorios de React

Esta combinación hace que la actualización de React funcione y, por extensión, hace que la experiencia de Feliz sea realmente cercana a la de JS o TS nativos. Espero que esto aclare la confusión. Si tienes más preguntas, házmelo saber 😉

¡Guau! ¡Simplemente guau! La persona tonta hace una pregunta estúpida y el chico inteligente responde con tres hojas A4 llenas de información y explicaciones relevantes. 🤯 ¡Simplemente rockeas, hombre! ¡Muchas gracias! ❤️ Ahora lo entiendo y comenzaré a usar Attribute en su lugar.

¿Todavía se recomienda nombrar los componentes de alguna manera (como lo hicimos usando el primer parámetro de React.functionComponent ) o esto ya no es necesario para el enfoque de atributos?

Ahora lo entiendo y comenzaré a usar Attribute en su lugar.

¡Impresionante! Permítame si encuentra algún problema 😉 ahora mismo, el único problema que debe tener en cuenta es usar un tipo de registro, ya que los accesorios de entrada serán un poco problemáticos para React-refresh, por lo que puede usar un registro anónimo en su lugar o parámetros primitivos. Espero que el problema se solucione pronto para poder documentar [<ReactComponent>] sin ninguna advertencia.

¿Todavía se recomienda nombrar los componentes de alguna manera (como lo hicimos usando el primer parámetro de React.functionComponent) o esto ya no es necesario para el enfoque de atributos?

No, el único requisito es que los componentes se compilen como valores en mayúsculas, que es una de las cosas que hace [<ReactComponent>] con la definición de la función: sonrisa: puede realizar la implementación aquí

@Dzoukr, la única razón para usar nombres para sus componentes de reacción es mejorar las herramientas de depuración.

@Shmew Sí, pero no hay una sobrecarga en el constructor ReactComponent para agregar ese nombre, por eso se pregunta.

Entonces, continuando con las preguntas [<ReactComponent>] vs functionComponent : ¡ganchos!

Tengo un componente que necesita inicializar algún estado. ¡Afortunadamente, tenemos muchos ganchos finos disponibles! Escribo esto:

[<ReactComponent>]
let Entrypoint() =
    let drawing, updateDrawing = React.useState(Deferred.HasNotStartedYet)
    let loader = React.useDeferredCallback((fun () -> loadDrawing()), updateDrawing)

    React.useEffect(loader, [||])
    // etc

Por desgracia, cuando intento ejecutar esto, mi consola está triste y llena de errores:

Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
    React 

He pasado por los pasos de depuración de reacción anteriores; ninguno parece ser cierto. ¿Debería funcionar esto? ¿Es esto solo una cosa de Fable 3? (Todavía estoy usando Fable 2.)

Tengo entendido que el atributo reactcomponent necesita fable 3 para funcionar porque es un complemento del compilador de fable 3

@landy ah, seguro que lo harás. Déjame poner en funcionamiento Fable 3, te informaré en un minuto

¡Oye! Sí, eso me arregló: utilicé este PR como guía para la conversión.

¿Fue útil esta página
0 / 5 - 0 calificaciones