run react example code apps app javascript reactjs react-native web-deployment

javascript - example - ¿Cómo actualizar el estado de los padres en React?



react native web example (12)

Mi estructura se ve de la siguiente manera:

Component 1 - |- Component 2 - - |- Component 4 - - - |- Component 5 Component 3

El componente 3 debería mostrar algunos datos dependiendo del estado del componente 5. Dado que los accesorios son inmutables, no puedo simplemente guardar su estado en el componente 1 y reenviarlo, ¿verdad? Y sí, he leído sobre redux, pero no quiero usarlo. Espero que sea posible resolverlo solo con reaccionar. ¿Me equivoco?


-Podemos crear ParentComponent y con el método handleInputChange para actualizar el estado ParentComponent. Importe el ChildComponent y pasamos dos accesorios del componente padre al hijo, es decir, la función handleInputChange y el recuento.

import React from ''react''; import { func, number } from ''prop-types''; const ChildComponent = ({ handleInputChange, count }) => ( <input onChange={handleInputChange} value={count} name="count" /> ); ChildComponent.propTypes = { count: number, handleInputChange: func.isRequired, }; ChildComponent.defaultProps = { count: 0, }; export default ChildComponent;

  • Ahora creamos el archivo ChildComponent y lo guardamos como ChildComponent.jsx. Este componente no tiene estado porque el componente hijo no tiene un estado. Utilizamos la biblioteca de tipos de utilería para la verificación de tipos de utilería.

    class Parent extends React.Component { handler = (Value_Passed_From_SubChild) => { console.log("Parent got triggered when a grandchild button was clicked"); console.log("Parent->Child->SubChild"); console.log(Value_Passed_From_SubChild); } render() { return <Child handler = {this.handler} /> } } class Child extends React.Component { render() { return <SubChild handler = {this.props.handler}/ > } } class SubChild extends React.Component { constructor(props){ super(props); this.state = { somethingImp : [1,2,3,4] } } render() { return <button onClick = {this.props.handler(this.state.somethingImp)}>Clickme<button/> } } React.render(<Parent />,document.getElementById(''app'')); HTML ---- <div id="app"></div>


Cuando necesite comunicarse entre el niño y el padre en cualquier nivel inferior, entonces es mejor hacer uso del contexto . En el componente principal, defina el contexto que puede invocar el elemento secundario, como

Componente principal en su caso componente 3

static childContextTypes = { parentMethod: React.PropTypes.func.isRequired }; getChildContext() { return { parentMethod: (parameter_from_child) => this.parentMethod(parameter_from_child) }; } parentMethod(parameter_from_child){ // update the state with parameter_from_child }

Ahora en el componente hijo (componente 5 en su caso), solo dígale a este componente que quiere usar el contexto de su padre.

static contextTypes = { parentMethod: React.PropTypes.func.isRequired }; render(){ return( <TouchableHighlight onPress={() =>this.context.parentMethod(new_state_value)} underlayColor=''gray'' > <Text> update state in parent component </Text> </TouchableHighlight> )}

puedes encontrar el proyecto Demo en el repo


Encontré la siguiente solución de trabajo para pasar el argumento de la función Click del elemento secundario al componente primario con param:

clase para padres:

class Parent extends React.Component { constructor(props) { super(props) // Bind the this context to the handler function this.handler = this.handler.bind(this); // Set some state this.state = { messageShown: false }; } // This method will be sent to the child component handler(param1) { console.log(param1); this.setState({ messageShown: true }); } // Render the child component and set the action property with the handler as value render() { return <Child action={this.handler} /> }}

clase infantil:

class Child extends React.Component { render() { return ( <div> {/* The button will execute the handler function set by the parent component */} <Button onClick={this.props.action.bind(this,param1)} /> </div> ) } }


Encontré la siguiente solución de trabajo para pasar el argumento de la función Click del elemento secundario al componente primario:

Versión con pasar un método ()

//ChildB component class ChildB extends React.Component { render() { var handleToUpdate = this.props.handleToUpdate; return (<div><button onClick={() => handleToUpdate(''someVar'')}> Push me </button> </div>) } } //ParentA component class ParentA extends React.Component { constructor(props) { super(props); var handleToUpdate = this.handleToUpdate.bind(this); var arg1 = ''''; } handleToUpdate(someArg){ alert(''We pass argument from Child to Parent: '' + someArg); this.setState({arg1:someArg}); } render() { var handleToUpdate = this.handleToUpdate; return (<div> <ChildB handleToUpdate = {handleToUpdate.bind(this)} /></div>) } } if(document.querySelector("#demo")){ ReactDOM.render( <ParentA />, document.querySelector("#demo") ); }

Mira JSFIDDLE

Versión con pasar una función de flecha

//ChildB component class ChildB extends React.Component { render() { var handleToUpdate = this.props.handleToUpdate; return (<div> <button onClick={() => handleToUpdate(''someVar'')}> Push me </button> </div>) } } //ParentA component class ParentA extends React.Component { constructor(props) { super(props); } handleToUpdate = (someArg) => { alert(''We pass argument from Child to Parent: '' + someArg); } render() { return (<div> <ChildB handleToUpdate = {this.handleToUpdate} /></div>) } } if(document.querySelector("#demo")){ ReactDOM.render( <ParentA />, document.querySelector("#demo") ); }

Mira JSFIDDLE


He usado una respuesta de alta calificación de esta página muchas veces, pero mientras aprendía React, encontré una mejor manera de hacerlo, sin vinculación y sin función en línea dentro de los accesorios.

Solo mira aquí:

class Parent extends React.Component { constructor() { super(); this.state={ someVar: value } } handleChange=(someValue)=>{ this.setState({someVar: someValue}) } render() { return <Child handler={this.handleChange} /> } } export const Child = ({handler}) => { return <Button onClick={handler} /> }

La clave está en una función de flecha:

handleChange=(someValue)=>{ this.setState({someVar: someValue}) }

Puedes leer más here . Espero que esto sea útil para alguien =)


Me gusta la respuesta con respecto a pasar funciones, es una técnica muy útil.

Por otro lado, también puede lograr esto usando pub / sub o usando una variante, un despachador, como lo hace Flux . La teoría es súper simple, haga que el componente 5 envíe un mensaje que el componente 3 está escuchando. El componente 3 luego actualiza su estado, lo que desencadena el renderizado. Esto requiere componentes con estado que, según su punto de vista, pueden ser o no un antipatrón. Estoy en contra de ellos personalmente y preferiría que algo más esté escuchando los despachos y cambie el estado desde arriba hacia abajo (Redux hace esto, pero agrega terminología adicional).

import { Dispatcher } from flux import { Component } from React const dispatcher = new Dispatcher() // Component 3 // Some methods, such as constructor, omitted for brevity class StatefulParent extends Component { state = { text: ''foo'' } componentDidMount() { dispatcher.register( dispatch => { if ( dispatch.type === ''change'' ) { this.setState({ text: ''bar'' }) } } } render() { return <h1>{ this.state.text }</h1> } } // Click handler const onClick = event => { dispatcher.dispatch({ type: ''change'' }) } // Component 5 in your example const StatelessChild = props => { return <button onClick={ onClick }>Click me</button> }

Los paquetes del despachador con Flux son muy simples, simplemente registra devoluciones de llamada e invoca cuando ocurre cualquier despacho, pasando por el contenido del despacho (en el ejemplo anterior no hay payload con el despacho, simplemente una identificación de mensaje). Puede adaptar esto al pub / sub tradicional (por ejemplo, usando EventEmitter de eventos, o alguna otra versión) muy fácilmente si eso tiene más sentido para usted.


Para la comunicación entre padres e hijos, debe pasar una función que establezca el estado de padres a hijos, de esta manera

class Parent extends React.Component { constructor(props) { super(props) this.handler = this.handler.bind(this) } handler(someValue) { this.setState({ someVar: someValue }) } render() { return <Child handler = {this.handler} /> } } class Child extends React.Component { render() { return <Button onClick = {this.props.handler}/ > } }

De esta manera, el niño puede actualizar el estado del padre con la llamada de una función pasada con accesorios.

Pero tendrá que repensar la estructura de sus componentes, porque entiendo que los componentes 5 y 3 no están relacionados.

Una posible solución es envolverlos en un componente de nivel superior que contendrá el estado de los componentes 1 y 3. Este componente establecerá el estado de nivel inferior a través de accesorios.


Parece que solo podemos pasar datos de padre a hijo a medida que reacciona promueve el Flujo de datos unidireccional, pero para hacer que el padre se actualice cuando algo sucede en su "componente hijo", generalmente usamos lo que se llama una "función de devolución de llamada".

Pasamos la función definida en el padre al hijo como "accesorios" y llamamos a esa función desde el hijo que la activa en el componente padre.

import React, { Component } from ''react''; import ChildComponent from ''./ChildComponent''; class ParentComponent extends Component { constructor(props) { super(props); this.handleInputChange = this.handleInputChange.bind(this); this.state = { count: '''', }; } handleInputChange(e) { const { value, name } = e.target; this.setState({ [name]: value }); } render() { const { count } = this.state; return ( <ChildComponent count={count} handleInputChange={this.handleInputChange} /> ); } }

En este ejemplo, podemos pasar datos desde SubChild -> Child -> Parent pasando la función a su hijo directo.


Quiero agradecer a la respuesta más votada por darme la idea de mi propio problema, básicamente, la variación de la misma con la función de flecha y pasar el parámetro del componente secundario:

class Parent extends React.Component { constructor(props) { super(props) // without bind, replaced by arrow func below } handler = (val) => { this.setState({ someVar: val }) } render() { return <Child handler = {this.handler} /> } } class Child extends React.Component { render() { return <Button onClick = {() => this.props.handler(''the passing value'')}/ > } }

Espero que ayude a alguien.


Si este mismo escenario no se extiende a todas partes, puede usar el contexto de React, especialmente si no desea introducir todos los gastos generales que introducen las bibliotecas de administración de estado. Además, es más fácil de aprender. Pero tenga cuidado, podría usarlo en exceso y comenzar a escribir código incorrecto. Básicamente, usted define un componente Contenedor (que mantendrá y mantendrá esa parte del estado para usted) haciendo que todos los componentes interesados ​​en escribir / leer esa parte de sus datos sean sus elementos secundarios (no necesariamente elementos secundarios directos)

https://reactjs.org/docs/context.html

También podría usar React simple en su lugar.

<Footer action={()=>this.setState({showChart: true})} /> <footer className="row"> <button type="button" onClick={this.props.action}>Edit</button> {console.log(this.props)} </footer> Try this example to write inline setState, it avoids creating another function.

pase doSomethingAbout5 hasta el Componente 1

<Component1> <Component2 onSomethingHappenedIn5={somethingAbout5 => this.setState({somethingAbout5})}/> <Component5 propThatDependsOn5={this.state.somethingAbout5}/> <Component1/>

Si este es un problema común, debe comenzar a pensar en trasladar todo el estado de la aplicación a otro lugar. Tienes algunas opciones, las más comunes son:

https://redux.js.org/

Flux

Básicamente, en lugar de administrar el estado de la aplicación en su componente, envía comandos cuando sucede algo para actualizar el estado. Los componentes también extraen el estado de este contenedor para que todos los datos estén centralizados. Esto no significa que ya no pueda usar el estado local, pero ese es un tema más avanzado.


entonces, si quieres actualizar el componente padre,

class ParentComponent extends React.Component { constructor(props){ super(props); this.state = { page:0 } } handler(val){ console.log(val) // 1 } render(){ return ( <ChildComponent onChange={this.handler} /> ) } } class ChildComponent extends React.Component { constructor(props) { super(props); this.state = { page:1 }; } someMethod = (page) => { this.setState({ page: page }); this.props.onChange(page) } render() { return ( <Button onClick={() => this.someMethod()} > Click </Button> ) } }

Aquí onChange es un atributo con el método "controlador" vinculado a su instancia. Pasamos el manejador de métodos al componente de clase Child, para recibir a través de la propiedad onChange en su argumento props.

El atributo onChange se establecerá en un objeto de utilería como este:

props ={ onChange : this.handler }

y pasó al componente hijo

Por lo tanto, el componente Child puede acceder al valor del nombre en el objeto props como este props.onChange

Se realiza mediante el uso de accesorios de renderizado.

Ahora el componente Child tiene un botón "Click" con un evento onclick configurado para llamar al método del controlador que se le pasó a través de onChnge en su objeto de argumento de accesorios. Así que ahora this.props.onChange in Child contiene el método de salida en la clase principal Referencia y créditos: bits y piezas


<Footer action={()=>this.setState({showChart: true})} /> <footer className="row"> <button type="button" onClick={this.props.action}>Edit</button> {console.log(this.props)} </footer> Try this example to write inline setState, it avoids creating another function.