gaurav5430
Para renderizar componentes/jsx más pequeños dentro de un componente más grande, existen varios enfoques que se pueden seguir. Por ejemplo, considera esto:
Método 1:
function BigComponent(props) {
const renderSmallComponent1 = () => <div>{props.a}</div>;
const renderSmallComponent2 = () => <div>{props.b}</div>;
return (
<div>
{renderSmallComponent1()}
{renderSmallComponent2()}
</div>
)
}
Método 2:
function BigComponent(props) {
const smallComponent1 = <div>{props.a}</div>;
const smallComponent2 = <div>{props.b}</div>;
return (
<div>
{smallComponent1}
{smallComponent2}
</div>
)
}
Método 3:
function SmallComponent1({ a }) {
return <div>{a}</div>;
}
function SmallComponent2({ b }) {
return <div>{b}</div>;
}
function BigComponent(props) {
return (
<div>
<SmallComponent1 a={props.a} />
<SmallComponent2 b={props.b} />
</div>
)
}
Solo estoy tratando de entender la diferencia en estos 3 en términos de
- experiencia de desarrollo,
- cómo los trata el marco,
- ¿Hay optimizaciones de rendimiento?
- ¿Hay diferencias en los comportamientos de tiempo de ejecución en todos estos?
- ¿Alguno de los dos es mejor para usar en ciertos escenarios?
Estas son las cosas que entiendo:
- en el Método 3, todos
SmallComponent
son componentes de React que se renderizan en otro componente, por lo que tendrían un ciclo de vida del componente, mientras que en el método 1 y 2, son jsx simples, que no tienen ciclo de vida, por lo que no se montarían/desmontarían como componentes de React - en el Método 2, estaríamos evaluando ansiosamente el JSX ya que es directamente una variable, mientras que en el método 1, solo se evaluaría cuando se llama a la función en render. Entonces, en caso de que tengamos alguna representación condicional, la evaluación ansiosa podría ser un desperdicio.
Algunos otros artículos útiles:
- https://medium.com/missive-app/45-faster-react-function-components-now-3509a668e69f
- https://kentcdodds.com/blog/dont-call-a-react-function-component
ACTUALIZAR: parece que la observación 1 es incorrecta ya que los 3 aún se procesarían como componentes reactivos y, por lo tanto, tendrían un ciclo de vida del componente. Entonces reaccionar los montaría/desmontaría.
ACTUALIZAR 2: No, la observación 1 es correcta, los métodos 1 y 2 se tratan como jsx regulares como parte de BigComponent y no se tratan como componentes de reacción que tienen un ciclo de vida.
ACTUALIZAR 3: Hay otro método Método 4:
function BigComponent(props) {
const SmallComponent1 = () => {
return <div>{props.a}</div>;
}
const SmallComponent2 = () => {
return <div>{props.b}</div>;
}
return (
<div>
<SmallComponent1 />
<SmallComponent2 />
</div>
)
}
esto es similar al Método 3, pero el Método 3 frente al Método 4 es ligeramente diferente en la ejecución, cuando se depura a través de herramientas de desarrollo.
Firoj Siddiki
Método 2:
function BigComponent(props) {
const smallComponent1 = <div>{props.a}</div>;
const smallComponent2 = <div>{props.b}</div>;
return (
<div>
{smallComponent1}
{smallComponent2}
</div>
)
}
- Si desea una interfaz de usuario grande en una interfaz de usuario más pequeña separada, este método le brindará el mejor rendimiento porque
- Todavía es solo un gran componente de la interfaz de usuario.
- reaccionar solo hay que resolver las referencias de variables.
- mientras se vuelve a renderizar, BigComponent, smallComponent1 y smallComponent2 se renderizan juntos como una sola unidad.
- smallComponent1 y smallComponent2 no pueden tener su propio estado, ciclos de vida y ganchos.
- smallComponent1 y 2 deben ser reinicializado cada vez que se cambia el estado de Bigcomponent. Por lo tanto, es una buena práctica envolverlos con
useMemo()
si el resultado de esos componentes pequeños proviene de un cálculo costoso.
Método 3:
function SmallComponent1({ a }) {
return <div>{a}</div>;
}
function SmallComponent2({ b }) {
return <div>{b}</div>;
}
function BigComponent(props) {
return (
<div>
<SmallComponent1 a={props.a} />
<SmallComponent2 b={props.b} />
</div>
)
}
-
React necesita resolver la referencia y ejecutar la función después de resolver la referencia.
-
Es una composición de los componentes secundarios reales de reaccionar en un componente grande.
-
Los componentes secundarios pueden tener sus propios
hooks
. -
Los componentes secundarios son no reinicializado pero se vuelven a renderizar si se cambia el estado de BigComponent.
-
Existe la posibilidad de que SmallComponent1 y SmallComponent2 se vuelvan a renderizar varias veces en el renderizado de BigComponents una vez si los componentes pequeños están actualizando su propio estado en función del cambio de accesorios en los padres.
-
si se supone que cada SmallComponents debe usar múltiples accesorios cuyo estado de BigComponents, Keeping SmallComponents fuera de BigComponent ofrece una buena experiencia de desarrollador.
-
Espero que el Método 1 y el Método 4 también se puedan entender usando estos puntos anteriores.
-
Nota: los componentes secundarios almacenados en variables y componentes secundarios como función se vuelven engañosos si la lógica de su aplicación usa ref o elemento DOM para mantener el enfoque o el punto de anclaje de la representación.
t0mgerman
¿Has echado un vistazo al JS compilado en un proyecto de React?
Las etiquetas JSX se transforman esencialmente en React.createElement
declaraciones. Usted puede lea los documentos aquí. Esencialmente la sintaxis es:
React.createElement(FunctionOrClassComponent, { props }, ...children)
En los tres ejemplos, esto ocurriría. En los tres ejemplos, los componentes más pequeños son componentes funcionales en lugar de componentes de clase. Es decir, no tienen los métodos de ciclo de vida React de un componente de clase, pero puede use ganchos React equivalentes, si lo desea.
Editado: La evaluación (instanciación y representación) depende de su lógica de representación. Si tiene declaraciones de representación condicional o sus funciones devuelven un valor nulo (o menos contenido) en función de ciertas condiciones, entonces, obviamente, está haciendo menos trabajo. Y como señaló correctamente en los comentarios a continuación, cuando asigna un JSX.Element a una variable, eso se evalúa en línea en lugar de como resultado de una función, por lo que eso sucede de inmediato.
Para mí, los tres son enfoques válidos. Para responder a sus preguntas:
- experiencia de desarrollo,
- para componentes pequeños con estado mínimo, los componentes funcionales como variables o lambdas son convenientes para escribir y leer/analizar fácilmente al revisar el código en una fecha posterior. Cuando un componente se vuelve más complejo, es posible que deba reconsiderar cómo está escrito y tal vez usar componentes de clase.
- cómo los trata el marco,
- que yo sepa, el marco trata los tres ejemplos de la misma manera en términos de compilación. No estoy seguro acerca de la optimización de renderizado.
- ¿Hay optimizaciones de rendimiento?
- sus ejemplos no representan nada computacionalmente oneroso, por lo que las opciones de optimización del rendimiento no son tan obvias
- ¿Hay diferencias en los comportamientos de tiempo de ejecución en todos estos?
- todos se traducen a elementos React, se controlan los cambios de accesorios y se vuelven a renderizar si los padres vuelven a renderizar (si no se emplean cosas como React.memo); puede haber diferencias con respecto a los elementos basados en clases, pero supongo que eso las diferencias de tiempo de ejecución entre sus tres ejemplos son mínimas
- ¿Alguno de los dos es mejor para usar en ciertos escenarios?
- Las diferencias entre los tres son más una cuestión de estándares o etiqueta que de resultados funcionales. Como desarrollador, podría leer y comprender los tres, pero al trabajar en equipo, me gustaría ver un enfoque estándar.
-
Con respecto a la evaluación ansiosa: el método 1 solo evaluaría las cosas cuando se llama a la función dentro de render/return, pero el método 2 evaluaría las cosas incluso antes de eso, ya que es una variable
– gaurav5430
21 de abril de 2021 a las 3:11
-
Con respecto al uso de ganchos: en el método 1 y 2, creo que incluso si pudiéramos usar ganchos, pertenecerían al padre, y no a estos pequeños componentes.
– gaurav5430
21 de abril de 2021 a las 3:16
-
Disculpas, es tarde aquí. Confundí lo que estabas diciendo sobre la evaluación con la carga ansiosa (en lugar de la carga diferida). Tiene razón, el método 2 evaluaría las cosas en línea, ya que no son funciones sino declaraciones de elementos JSX (como variables). Para los métodos 1 y 3, si usó ganchos en los componentes pequeños y declaró y asignó las salidas de gancho para bloquear variables de alcance (usando let o const), pertenecerían a los componentes pequeños… solo se elevarían al componente principal si usaste var.
– t0mgerman
21 de abril de 2021 a las 3:22
-
Lo siento, también cometí un error allí … Quise decir que solo pertenecerían al componente principal si los declarara allí.
– t0mgerman
21 de abril de 2021 a las 3:32
Pareces entender los casos bastante bien. No estoy seguro de qué aspecto en particular quieres profundizar.
– hackape
21 de abril de 2021 a las 1:49
Preguntas como: ¿existe un escenario en el que uno de estos métodos funcione de manera diferente a los demás, o no funcione en absoluto? ¿Pueden siempre reemplazarse entre sí?
– gaurav5430
21 de abril de 2021 a las 2:46
Hmm, todavía me parece una pregunta abierta. Realmente no sé por dónde empezar porque puedo construir todo tipo de ejemplos para ilustrar comportamientos diferentes.
– hackape
21 de abril de 2021 a las 3:48
@hackape, creo que diferentes tipos de ejemplos seguirían siendo útiles y podrían responder las partes principales de la pregunta, que se trata esencialmente de las diferencias en estos 3 enfoques
– gaurav5430
21 de abril de 2021 a las 3:51
En lugar de analizar casos de uso especiales, creo que el mejor enfoque sería aprender el trabajo interno de reaccionar. Una vez que aprendes la “física”, sabes cómo hacer toda la “ingeniería”.
– hackape
21 de abril de 2021 a las 3:51