¿No hay una manera simple de pasar un niño props
a su padre usando eventos, en React.js?
var Child = React.createClass({
render: function() {
<a onClick={this.props.onClick}>Click me</a>
}
});
var Parent = React.createClass({
onClick: function(event) {
// event.component.props ?why is this not available?
},
render: function() {
<Child onClick={this.onClick} />
}
});
Sé que puedes usar componentes controlados para pasar el valor de una entrada, pero sería bueno pasar todo el kit n 'kaboodle. A veces, el componente secundario contiene un conjunto de información que preferiría no tener que buscar.
¿Quizás hay una manera de vincular el componente al evento?
ACTUALIZACIÓN - 9/1/2015
Después de usar React durante más de un año, y estimulado por la respuesta de Sebastien Lorber, he concluido que pasar componentes infantiles como argumentos para las funciones en los padres no es, de hecho, la forma React, ni fue una buena idea. He cambiado la respuesta.
javascript
reactjs
KendallB
fuente
fuente
Respuestas:
Editar : vea los ejemplos finales para los ejemplos actualizados de ES6.
Esta respuesta simplemente maneja el caso de la relación directa padre-hijo. Cuando padre e hijo tengan potencialmente muchos intermediarios, marque esta respuesta .
Otras soluciones están perdiendo el punto
Si bien aún funcionan bien, a otras respuestas les falta algo muy importante.
¡El padre ya tiene ese accesorio de niño! : si el niño tiene un accesorio, ¡es porque su padre le proporcionó ese accesorio al niño! ¿Por qué quieres que el niño pase el accesorio al padre, mientras que el padre obviamente ya tiene ese accesorio?
Mejor implementación
Niño : realmente no tiene que ser más complicado que eso.
Padre con hijo único : usando el valor que le pasa al hijo
JsFiddle
Padre con lista de hijos : todavía tiene todo lo que necesita en el padre y no necesita complicarlo más.
JsFiddle
También es posible usar
this.handleChildClick.bind(null,childIndex)
y luego usarthis.state.childrenData[childIndex]
Tenga en cuenta que estamos vinculados con un
null
contexto porque, de lo contrario, React emite una advertencia relacionada con su sistema de enlace automático. Usar nulo significa que no desea cambiar el contexto de la función. Ver también .Sobre encapsulación y acoplamiento en otras respuestas
Esta es para mí una mala idea en términos de acoplamiento y encapsulación:
Uso de accesorios : como expliqué anteriormente, ya tiene los accesorios en el padre, por lo que es inútil pasar todo el componente hijo para acceder a los accesorios.
Uso de referencias : ya tiene el objetivo de clic en el evento, y en la mayoría de los casos esto es suficiente. Además, podría haber usado una referencia directamente sobre el niño:
Y acceda al nodo DOM en el padre con
Para casos más avanzados en los que desea acceder a múltiples referencias del niño en el padre, el niño podría pasar todos los nodos dom directamente en la devolución de llamada.
El componente tiene una interfaz (accesorios) y el padre no debe asumir nada sobre el funcionamiento interno del niño, incluida su estructura DOM interna o para qué nodos DOM declara referencias. Un padre que usa una referencia de un niño significa que acopla firmemente los 2 componentes.
Para ilustrar el problema, tomaré esta cita sobre Shadow DOM , que se usa dentro de los navegadores para representar elementos como controles deslizantes, barras de desplazamiento, reproductores de video ...:
El problema es que si deja que los detalles de implementación secundarios se filtren en el elemento primario, le resultará muy difícil refactorizar el elemento secundario sin afectarlo. Esto significa que, como autor de la biblioteca (o como editor del navegador con Shadow DOM), esto es muy peligroso porque permite que el cliente acceda demasiado, lo que dificulta la actualización del código sin romper la retrocompatibilidad.
Si Chrome hubiera implementado su barra de desplazamiento permitiendo que el cliente acceda a los nodos dom internos de esa barra de desplazamiento, esto significa que el cliente puede tener la posibilidad de simplemente romper esa barra de desplazamiento, y que las aplicaciones se romperían más fácilmente cuando Chrome realiza su actualización automática después de refactorizar el barra de desplazamiento ... En cambio, solo dan acceso a algunas cosas seguras como personalizar algunas partes de la barra de desplazamiento con CSS.
Sobre usar cualquier otra cosa
Pasar todo el componente en la devolución de llamada es peligroso y puede dar lugar a los desarrolladores novatos que hacer cosas muy extrañas como llamar
childComponent.setState(...)
ochildComponent.forceUpdate()
, o asignándole nuevas variables, dentro de la matriz, por lo que toda la aplicación mucho más difícil de razonar acerca.Editar: ejemplos de ES6
Como muchas personas ahora usan ES6, estos son los mismos ejemplos para la sintaxis de ES6
El niño puede ser muy simple:
El padre puede ser una clase (y eventualmente puede administrar el estado en sí, pero lo paso como accesorio aquí:
Pero también se puede simplificar si no necesita administrar el estado:
JsFiddle
ADVERTENCIA PERF (aplica a ES5 / ES6): si está utilizando
PureComponent
oshouldComponentUpdate
, las implementaciones anteriores no se optimizarán de manera predeterminada porque se usanonClick={e => doSomething()}
o se vinculan directamente durante la fase de representación, ya que creará una nueva función cada vez que se muestre el elemento primario. Si se trata de un cuello de botella de rendimiento en su aplicación, puede pasar los datos a los elementos secundarios y reinyectarlos dentro de la devolución de llamada "estable" (establecida en la clase principal y vinculada althis
constructor de la clase) para que laPureComponent
optimización pueda iniciarse, o usted puede implementar el suyo propioshouldComponentUpdate
e ignorar la devolución de llamada en la verificación de comparación de accesorios.También puede usar la biblioteca Recompose , que proporciona componentes de orden superior para lograr optimizaciones ajustadas:
En este caso, podría optimizar el componente Hijo utilizando:
fuente
props
. ¿De acuerdo?How do I know which of my children was chosen among a group?
esto no es realmente parte de la pregunta original, pero incluí la solución en mi respuesta. A diferencia de su edición, creo que no es necesario modificar el niño en absoluto, incluso cuando se trata de una lista, ya que puede usarlobind
directamente en el padre.onClick={this.handleChildClick.bind(null,childData)}
que mencionó sobre la vinculación automática, ¿sigue siendo aplicable ahora que React no se ha incluido en el modelo de clase ? He leído muchas cosas, pero esta parte todavía me confunde. Porclass model
cierto, estoy usando ES6 , así que cambiénull
athis
y mi código todavía parece funcionar. ¿Cómo traducirías esa parte de tu código al estilo ES6?Actualización (1/9/15): El OP ha convertido esta pregunta en un objetivo móvil. Ha sido actualizado nuevamente. Entonces, me siento responsable de actualizar mi respuesta.
Primero, una respuesta a su ejemplo proporcionado:
Si, esto es posible.
Puede resolver esto actualizando Child's
onClick
para que seathis.props.onClick.bind(null, this)
:El controlador de eventos en su padre puede acceder al componente y al evento de la siguiente manera:
Instantánea de JSBin
Pero la pregunta en sí es engañosa
El padre ya sabe del niño
props
.Esto no está claro en el ejemplo proporcionado porque en realidad no se proporcionan accesorios. Este código de muestra podría respaldar mejor la pregunta que se hace:
Se vuelve mucho más claro en este ejemplo que ya sabes cuáles son los accesorios del Niño.
Instantánea de JSBin
Si realmente se trata de usar los accesorios de un niño ...
Si realmente se trata de usar los accesorios de un niño, puede evitar cualquier conexión con el niño por completo.
JSX tiene una API de atributos extendidos que uso a menudo en componentes como Child. Toma todo
props
y los aplica a un componente. El niño se vería así:Permitiéndole usar los valores directamente en el padre:
Instantánea de JSBin
Y no se requiere configuración adicional a medida que conecta componentes secundarios adicionales
Instantánea de JSBin
Pero sospecho que ese no es su caso de uso real. Así que vamos a cavar más ...
Un ejemplo práctico robusto
Es difícil hablar de la naturaleza genérica del ejemplo proporcionado. He creado un componente que demuestra un uso práctico para la pregunta anterior, implementado de una manera muy reactiva :
Ejemplo de trabajo de DTServiceCalculator Repo
DTServiceCalculator
Este componente es una calculadora de servicio simple. Le proporciona una lista de servicios (con nombres y precios) y calculará un total de los precios seleccionados.
Los niños son felizmente ignorantes
ServiceItem
es el componente hijo en este ejemplo. No tiene muchas opiniones sobre el mundo exterior. Se requiere un par de apoyos , uno de los cuales es una función que se llamará cuando se hace clic.<div onClick={this.props.handleClick.bind(this.props.index)} />
No hace nada más que llamar a la
handleClick
devolución de llamada proporcionada con laindex
[ fuente ] proporcionada .Los padres son niños
DTServicesCalculator
es el componente principal es este ejemplo. También es un niño. Miremos.DTServiceCalculator
crea una lista de componentes secundariosServiceItem
y les proporciona accesorios [ fuente ]. Es el componente principal deServiceItem
pero es el componente secundario del componente que le pasa la lista. No posee los datos. Por lo tanto, delega nuevamente el manejo del componente a su fuente de componente principal<ServiceItem chosen={chosen} index={i} key={id} price={price} name={name} onSelect={this.props.handleServiceItem} />
handleServiceItem
captura el índice, se pasa del elemento secundario y se lo proporciona a su elemento primario [ fuente ]Los dueños lo saben todo
El concepto de "Propiedad" es importante en React. Recomiendo leer más sobre esto aquí .
En el ejemplo que he mostrado, sigo delegando el manejo de un evento en el árbol de componentes hasta que lleguemos al componente que posee el estado.
Cuando finalmente llegamos allí, manejamos la selección / deselección de estado de la siguiente manera [ fuente ]
Conclusión
Intente mantener sus componentes más externos lo más opacos posible. Esfuércese por asegurarse de que tengan muy pocas preferencias sobre cómo un componente principal podría elegir implementarlas.
Tenga en cuenta quién posee los datos que está manipulando. En la mayoría de los casos, deberá delegar el manejo de eventos en el árbol al componente que posee ese estado.
Aparte: el patrón Flux es una buena forma de reducir este tipo de conexión necesaria en las aplicaciones.
fuente
Parent
podría tratarse de una Vista de controlador, mientrasChild
que solo es una Vista tonta (componente). Solo Controller-Views debe tener conocimiento de la aplicación. En este caso, aún pasarías la Acción deParent
aChild
como un accesorio. En lo que respecta a la acción en sí, Flux tiene un patrón fuertemente prescrito para interactuar entre las acciones para actualizar las vistas. facebook.github.io/flux/docs/…onClick={this.onClick.bind(null, this.state.text)}
no es necesario vincular el estado ya que el padre tiene eso. así que soloonClick={this.onClick}
funcionará. dondeonClick = ()=>{const text = this.state.text;..}
en los padresParece que hay una respuesta simple. Considera esto:
La clave está llamando
bind(null, this)
althis.props.onClick
evento, pasado del padre. Ahora, la función onClick acepta argumentoscomponent
, ANDevent
. Creo que es el mejor de todos los mundos.ACTUALIZACIÓN: 1/9/2015
Esta fue una mala idea: dejar que los detalles de implementación secundarios se filtren a los padres nunca fue un buen camino. Ver la respuesta de Sebastien Lorber.
fuente
this
dentro de la función (que de todos modos no es necesario), y el segundo se antepone como primer argumento cuando se llama a onClick.La pregunta es cómo pasar el argumento del componente hijo al padre. Este ejemplo es fácil de usar y probado:
Mira JSFIDDLE
fuente
Básicamente, utiliza accesorios para enviar información hacia y desde el niño y el padre.
Agregando a todas las maravillosas respuestas, permítanme dar un ejemplo simple que explica pasar valores del componente hijo al padre en React
App.js
Header.js
Main.js
Eso es todo, ahora puede pasar valores de su cliente al servidor.
Eche un vistazo a la función Cambiar en Header.js
Así es como inserta valores en los accesorios del cliente al servidor
fuente
Aquí hay una implementación simple de ES6 de 3 pasos usando el enlace de función en el constructor padre. Esta es la primera forma en que el tutorial de reacción oficial recomienda (también hay una sintaxis de campos de clase pública que no se cubre aquí). Puede encontrar toda esta información aquí https://reactjs.org/docs/handling-events.html
Vinculando las funciones de los padres para que los niños puedan llamarlos (¡Y pasar datos al padre!: D)
Función principal
Constructor principal
Prop transmitido al niño
Llamada de evento infantil
fuente
Este es un ejemplo sin usar el evento onClick. Simplemente paso una función de devolución de llamada al niño por accesorios. Con esa devolución de llamada, la llamada secundaria también devuelve datos. Me inspiraron los ejemplos en los documentos .
Pequeño ejemplo (esto está en un archivo tsx, por lo que los accesorios y los estados deben declararse por completo, eliminé algo de lógica de los componentes, por lo que es menos código).
* Actualización: es importante vincular esto a la devolución de llamada, de lo contrario, la devolución de llamada tiene el alcance del elemento secundario y no del principal. El único problema: es el padre "viejo" ...
SymptomChoser es el padre:
El síntoma es el niño (en los accesorios del niño declare la función de devolución de llamada, en la función seleccionada Síntoma se llama la devolución de llamada):
fuente