react logo examples ejemplos documentacion reactjs

reactjs - examples - react logo



Reactjs: ¿cómo modificar el estado del componente dinámico infantil o los accesorios del padre? (3)

Básicamente estoy tratando de hacer pestañas en reaccionar, pero con algunos problemas.

Aquí está el archivo page.jsx

<RadioGroup> <Button title="A" /> <Button title="B" /> </RadioGroup>

Cuando hace clic en el botón A, el componente RadioGroup necesita quitar la selección del botón B.

"Seleccionado" solo significa un className de un estado o propiedad

Aquí está RadioGroup.jsx :

module.exports = React.createClass({ onChange: function( e ) { // How to modify children properties here??? }, render: function() { return (<div onChange={this.onChange}> {this.props.children} </div>); } });

La fuente de Button.jsx realidad no importa, tiene un botón de radio HTML que activa el evento DOM onChange nativo

El flujo esperado es:

  • Haga clic en el botón "A"
  • El botón "A" activa el cambio, evento DOM nativo, que sube hasta RadioGroup
  • RadioGroup onChange oyente se llama
  • RadioGroup necesita desmarcar el botón B. Esta es mi pregunta.

Aquí está el problema principal que estoy enfrentando: no puedo mover <Button> s en RadioGroup , porque la estructura de esto es tal que los niños son arbitrarios . Es decir, el marcado podría ser

<RadioGroup> <Button title="A" /> <Button title="B" /> </RadioGroup>

o

<RadioGroup> <OtherThing title="A" /> <OtherThing title="B" /> </RadioGroup>

He intentado algunas cosas.

Intento: En el controlador OnChange de RadioGroup:

React.Children.forEach( this.props.children, function( child ) { // Set the selected state of each child to be if the underlying <input> // value matches the child''s value child.setState({ selected: child.props.value === e.target.value }); });

Problema:

Invalid access to component property "setState" on exports at the top level. See react-warning-descriptors . Use a static method instead: <exports />.type.setState(...)

Intento: En el controlador OnChange de RadioGroup:

React.Children.forEach( this.props.children, function( child ) { child.props.selected = child.props.value === e.target.value; });

Problema: no pasa nada, incluso le doy a la clase Button un método componentWillReceiveProps

Intento: Intenté pasar un estado específico del padre a los hijos, por lo que puedo actualizar el estado principal y hacer que los niños respondan automáticamente. En la función de renderización de RadioGroup:

React.Children.forEach( this.props.children, function( item ) { this.transferPropsTo( item ); }, this);

Problema:

Failed to make request: Error: Invariant Violation: exports: You can''t call transferPropsTo() on a component that you don''t own, exports. This usually means you are calling transferPropsTo() on a component passed in as props or children.

Mala solución n. ° 1 : Utilice el método cloneWithProps react-addons.js para clonar los niños en el momento de la RadioGroup en RadioGroup para poder pasarles las propiedades

Mala solución # 2 : Implementar una abstracción alrededor de HTML / JSX para poder pasar las propiedades de forma dinámica (kill me):

<RadioGroup items=[ { type: Button, title: ''A'' }, { type: Button, title: ''B'' } ]; />

Y luego en RadioGroup construye dinámicamente estos botones.

Esta pregunta no me ayuda porque necesito representar a mis hijos sin saber lo que son


Los botones deben ser sin estado. En lugar de actualizar las propiedades de un botón explícitamente, simplemente actualice el estado propio del grupo y vuelva a procesarlo. El método de renderización del Grupo debería entonces ver su estado al renderizar los botones y pasar "activo" (o algo) solo al botón activo.


No estoy seguro de por qué dices que usar cloneWithProps es una mala solución, pero aquí hay un ejemplo de trabajo que lo usa.

var Hello = React.createClass({ render: function() { return <div>Hello {this.props.name}</div>; } }); var App = React.createClass({ render: function() { return ( <Group ref="buttonGroup"> <Button key={1} name="Component A"/> <Button key={2} name="Component B"/> <Button key={3} name="Component C"/> </Group> ); } }); var Group = React.createClass({ getInitialState: function() { return { selectedItem: null }; }, selectItem: function(item) { this.setState({ selectedItem: item }); }, render: function() { var selectedKey = (this.state.selectedItem && this.state.selectedItem.props.key) || null; var children = this.props.children.map(function(item, i) { var isSelected = item.props.key === selectedKey; return React.addons.cloneWithProps(item, { isSelected: isSelected, selectItem: this.selectItem, key: item.props.key }); }, this); return ( <div> <strong>Selected:</strong> {this.state.selectedItem ? this.state.selectedItem.props.name : ''None''} <hr/> {children} </div> ); } }); var Button = React.createClass({ handleClick: function() { this.props.selectItem(this); }, render: function() { var selected = this.props.isSelected; return ( <div onClick={this.handleClick} className={selected ? "selected" : ""} > {this.props.name} ({this.props.key}) {selected ? "<---" : ""} </div> ); } }); React.renderComponent(<App />, document.body);

Aquí hay un jsFiddle que lo muestra en acción.

EDITAR : aquí hay un ejemplo más completo con contenido de pestañas dinámicas: jsFiddle


Tal vez la mía es una solución extraña, pero ¿por qué no utilizar el patrón de observador?

RadioGroup.jsx

module.exports = React.createClass({ buttonSetters: [], regSetter: function(v){ buttonSetters.push(v); }, handleChange: function(e) { // ... var name = e.target.name; //or name this.buttonSetters.forEach(function(v){ if(v.name != name) v.setState(false); }); }, render: function() { return ( <div> <Button title="A" regSetter={this.regSetter} onChange={handleChange}/> <Button title="B" regSetter={this.regSetter} onChange={handleChange} /> </div> ); });

Button.jsx

module.exports = React.createClass({ onChange: function( e ) { // How to modify children properties here??? }, componentDidMount: function() { this.props.regSetter({name:this.props.title,setState:this.setState}); }, onChange:function() { this.props.onChange(); }, render: function() { return (<div onChange={this.onChange}> <input element .../> </div>); } });

tal vez requieres algo más, pero encontré esto muy poderoso,

Realmente prefiero usar un modelo externo que proporcione métodos de registro de observadores para varias tareas