Estoy tratando de encontrar la forma correcta de definir algunos componentes que podrían usarse de forma genérica:
<Parent>
<Child value="1">
<Child value="2">
</Parent>
Hay una lógica en curso para la representación entre los componentes principales y secundarios, por supuesto, se puede imaginar <select>
y <option>
como un ejemplo de esta lógica.
Esta es una implementación ficticia para el propósito de la pregunta:
var Parent = React.createClass({
doSomething: function(value) {
},
render: function() {
return (<div>{this.props.children}</div>);
}
});
var Child = React.createClass({
onClick: function() {
this.props.doSomething(this.props.value); // doSomething is undefined
},
render: function() {
return (<div onClick={this.onClick}></div>);
}
});
La pregunta es cada vez que se utiliza {this.props.children}
para definir un componente de envoltura, ¿cómo se transfiere alguna propiedad a todos sus elementos secundarios?
javascript
reactjs
react-jsx
más-
fuente
fuente
Respuestas:
Clonando niños con nuevos accesorios
Puede usar React.Children para iterar sobre los hijos y luego clonar cada elemento con nuevos accesorios (fusión superficial) usando React.cloneElement, por ejemplo:
Violín: https://jsfiddle.net/2q294y43/2/
Llamar a los niños como una función
También puede pasar accesorios a niños con accesorios de render . En este enfoque, los elementos secundarios (que pueden ser
children
o cualquier otro nombre de apoyo) es una función que puede aceptar cualquier argumento que desee pasar y devuelve los elementos secundarios:En lugar de
<React.Fragment>
o simplemente<>
también puede devolver una matriz si lo prefiere.Fiddle: https://jsfiddle.net/ferahl/y5pcua68/7/
fuente
value
pasadodoSomething
.Para una forma un poco más limpia de hacerlo, intente:
Editar: para usar con varios elementos secundarios individuales (el elemento secundario debe ser un componente) puede hacerlo. Probado en 16.8.6
fuente
this.props.children
) acloneElement
... que espera un ... elemento.React.Children.only
La función devuelve el único hijo o arroja una excepción si hay múltiples (esto no existiría si no hubiera un caso de uso).Prueba esto
Funcionó para mí usando react-15.1.
fuente
React.cloneElement()
directamente sin rodearlo en las<div>
etiquetas? Porque, ¿qué pasa si el niño es un<span>
(o algo más) y queremos preservar su tipo de elemento de etiqueta?React.cloneElement(React.Children.only(this.props.children), {...this.props})
lo que arrojará un error si se pasa más de un hijo. Entonces no necesitas envolver en un div.let {children, ...acyclicalProps} = this.props
y luegoReact.cloneElement(React.Children.only(children), acyclicalProps)
.Pase accesorios para dirigir a los niños.
Ver todas las otras respuestas
Pase datos globales compartidos a través del árbol de componentes a través del contexto
Descargo de responsabilidad: esta es una respuesta actualizada, la anterior utilizaba la antigua API de contexto
Se basa en el principio de consumidor / proporcionar. Primero, crea tu contexto
Luego use vía
y
Ejemplo completo, semi-pseudocódigo.
1 https://facebook.github.io/react/docs/context.html
fuente
this.context
): no fusionaba mágicamente el contexto con accesorios. Tenías que establecer y usar intencionalmente el contexto, que es otra cosa.Pasando accesorios a niños anidados
Con la actualización a Reaccionar 16.6 ahora puede usar React.createContext y contextType .
fuente
this
contextoPuede usar
React.cloneElement
, es mejor saber cómo funciona antes de comenzar a usarlo en su aplicación. Se presenta enReact v0.13
, sigue leyendo para obtener más información, así que algo junto con este trabajo para ti:Así que traiga las líneas de la documentación de React para que comprenda cómo funciona todo y cómo puede utilizarlas:
más aquí ...
fuente
La mejor manera, que le permite hacer la transferencia de propiedad es
children
como una funciónEjemplo:
fuente
nested components
. React no tiene patrones anidados, solo composiciones. Sí, los hijos deben ser una función, no hay conflictos, porque este es un hijo JSX válido. ¿Puedes dar un ejemplo connesting components
?<Parent>{props => <Nest><ChildComponent /></Nest>}</Parent>
lugar de (no funciona),<Parent><Nest>{props => <ChildComponent />}</Nest></Parent>
así que estoy de acuerdo en que esta es la mejor respuestaTypeError: children is not a function
Necesitaba corregir la respuesta aceptada arriba para que funcione usando eso en lugar de este puntero. Esta dentro del alcance de la función de mapa no tenía definida la función doSomething .
Actualización: esta solución es para ECMAScript 5, en ES6 no hay necesidad en var que = esto
fuente
bind()
doSomething
tomó un objeto, comodoSomething: function(obj) { console.log(obj) }
y en el Niño que se dicethis.props.doSomething(obj)
para cerrar la sesión"obj"
apply
método. usarbind()
en la función de renderizado creará una nueva función cada vez que se llame al método de renderizado.Manera más limpia considerando uno o más niños
fuente
this.props
. En general, solo recomendaría clonar con accesorios específicos, no todo el asunto.{...this.props}
no funcionó para mí, ¿es la forma{...child.props}
correcta?React.Children.map(children, child => React.cloneElement(child, props))
Ninguna de las respuestas aborda el problema de tener hijos que NO sean componentes React, como cadenas de texto. Una solución alternativa podría ser algo como esto:
fuente
Ya no lo necesitas
{this.props.children}
. Ahora usted puede envolver su componente secundario usandorender
enRoute
y pasar sus puntales como de costumbre:fuente
Parent.jsx:
Child.jsx:
y main.jsx:
ver ejemplo aquí: https://plnkr.co/edit/jJHQECrKRrtKlKYRpIWl?p=preview
fuente
Tal vez también pueda encontrar útil esta función, aunque muchas personas lo han considerado como un antipatrón que todavía se puede usar si sabe lo que está haciendo y diseña bien su solución.
Funcionan como componentes secundarios
fuente
Si tiene varios hijos a los que desea pasarles accesorios , puede hacerlo de esta manera, usando React.Children.map:
Si su componente tiene solo un hijo, no hay necesidad de mapear, simplemente puede clonarElement de inmediato:
fuente
De acuerdo con la documentación de
cloneElement()
Entonces cloneElement es lo que usarías para proporcionar accesorios personalizados a los niños. Sin embargo, puede haber varios elementos secundarios en el componente y necesitaría recorrerlo. Lo que otras respuestas sugieren es que las mapees con ellas
React.Children.map
. Sin embargo, aReact.Children.map
diferencia de losReact.cloneElement
cambios, las teclas del elemento anexan y extra.$
como prefijo. Consulte esta pregunta para más detalles: React.cloneElement dentro de React.Children.map está causando cambios en las claves de los elementosSi desea evitarlo, debe optar por la
forEach
función comofuente
Además de la respuesta @and_rest, así es como clono a los niños y agrego una clase.
fuente
Creo que un accesorio de render es la forma adecuada de manejar este escenario
Dejas que el padre proporcione los accesorios necesarios utilizados en el componente hijo, refactorizando el código principal para que se vea de la siguiente manera:
Luego, en el componente secundario, puede acceder a la función provista por el padre de esta manera:
Ahora la estructura final se verá así:
fuente
Método 1 - clonar niños
Método 2: usar contexto composable
El contexto le permite pasar un accesorio a un componente secundario profundo sin pasarlo explícitamente como accesorio a través de los componentes intermedios.
El contexto viene con inconvenientes:
Usando un contexto composable
fuente
{children}:{children:ReactNode}
?"children"
es de tipoReactNode
La forma más hábil de hacer esto:
fuente
Para cualquiera que tenga un solo elemento hijo, esto debería hacerlo.
fuente
¿Es esto lo que necesitabas?
fuente
Por alguna razón, React.children no funcionaba para mí. Esto es lo que funcionó para mí.
Solo quería agregar una clase al niño. similar a cambiar un accesorio
El truco aquí es el React.cloneElement . Puedes pasar cualquier accesorio de manera similar
fuente
Render props es el enfoque más preciso para este problema. En lugar de pasar el componente hijo al componente padre como accesorios hijos, deje que el padre represente el componente hijo manualmente. Render es accesorios integrados en react, que toma el parámetro de función. En esta función, puede permitir que el componente principal represente lo que desee con parámetros personalizados. Básicamente, hace lo mismo que los accesorios para niños, pero es más personalizable.
Ejemplo en codepen
fuente
Cuando utilice componentes funcionales, a menudo obtendrá el
TypeError: Cannot add property myNewProp, object is not extensible
error cuando intente establecer nuevas propiedadesprops.children
. Hay una solución para esto clonando los accesorios y luego clonando al niño con los nuevos accesorios.fuente