Flujo de escritura HOC de React (sin HOC)
Necesito escribir HOC para mi componente (y eso se preguntó millones de veces). Pero necesito hacer algo opuesto a lo típico con la inyección withSomething. Necesito agregar una propiedad adicional a mi componente externo y pasar todas las demás propiedades (desconocidas) al componente interno:
// @flow
import * as React from 'react'
// Esto es un ejemplo de un componente estándar que no hace nada
type Props = {| str: string, num: number |}
const Hello = ({ str, num }: Props): React.Node => {
console.log(str, num)
return <div>'Hello'</div>
}
// Este es el ejemplo estándar (y funcionando) del componente con la propiedad inyectada.
// Es equivalente a la currificación de prop, establezco la propiedad str en un valor predeterminado
type InnerInjected = {| str: string |}
const withInnerInject = <p>(
Component: React.AbstractComponent<$Exact<{ ...P, ...InnerInjected }>>,
): React.AbstractComponent<p> => {
return (props: P) => {
return <component str="aaa" {...props}=""></component>
}
}
const InnerInjectHello = withInnerInject(Hello)
// Y aquí está el ejemplo que no funciona.
export const withOuterInject = <p>(
Component: React.AbstractComponent<p>,
): React.AbstractComponent<p> => {
return (props: P) => {
// Necesito pasar el bool (u otra variable) a mi componente para realizar alguna acción basada en su valor y devolver el componente estándar con todas las propiedades de ese componente que aún no conozco.
const { bool, ...rest } = props
return <component {...rest}=""></component>
}
}
const OuterInjectHello = withOuterInject(Hello)
const Example = (): React.Node => {
return (
<>
{/* Ambas propiedades num y str se establecen como se desea */}
<hello num="{25}" str="algo">
{/* str se inyecta con el valor 'aaa' */}
<innerinjecthello num="{25}"></innerinjecthello>
{/* Funciona, pero la escritura es incorrecta */}
<outerinjecthello str="aa" num="{25}" bool=""></outerinjecthello>
)
}
He probado varias aproximaciones con $Diff<> y $Rest<>, pero simplemente no funcionan con los genéricos.
davy.ai
Para agregar una propiedad adicional al componente externo mientras se pasan todas las demás propiedades desconocidas al componente interno, puedes usar el tipo de utilidad
Omit
de TypeScript y el operador de propagación. Aquí tienes un ejemplo de implementación:En este ejemplo,
withPropiedadInyectada
es un Componente de Orden Superior que toma un componente inyectado (ComponenteInyectado
) y devuelve un nuevo componente (Envoltorio
) que envuelve al componente original (ComponenteEnvolvente
). El componenteEnvoltorio
recibe todas las propiedades y utiliza elComponenteInyectado
para agregar la propiedad inyectada (foo
) a la jerarquía del componente. ElComponenteEnvolvente
recibe todas las propiedades desconocidas (es decir, todas las propiedades exceptofoo
), que se seleccionan utilizando el tipo de utilidadPick
y el tipo de utilidadExclude
. La conversiónas Pick<p,></p,><keyof p,="" keyof="" propiedadesinyectadas="">>
es necesaria para ayudar a TypeScript a comprender que solo nos interesan las propiedades restantes que no se hayan proporcionado previamente por elComponenteInyectado
.Finalmente, se utiliza
withPropiedadInyectada
conReact.Fragment
como componente inyectado yComponenteInterno
como componente envuelto para crearComponenteExterno
, que tiene la propiedadfoo
agregada transmitida porReact.Fragment
y todas las demás propiedades transmitidas aComponenteInterno
.Ten en cuenta que esta implementación utiliza TypeScript en lugar de Flow, pero el concepto debería ser similar. TypeError: get_notifier no es una función