¿Cómo puedo actualizar el estado de los padres en React?

10 minutos de lectura

¿Como puedo actualizar el estado de los padres en React
Wojciech Kulma

Mi estructura queda de la siguiente manera:

Component 1

 - |- Component 2


 - - |- Component 4


 - - -  |- Component 5

Component 3

El Componente 3 debería mostrar algunos datos según el 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?

  • muy fácil: pase la función padre-setState-Function a través de la propiedad al componente secundario: {this.setState(p)}} /> En el componente secundario, llámelo a través de this.props. setState({miObj,…});

    –Marcel Ennix

    8 mayo 2018 a las 21:47

  • <MyChildComponent setState={(s,c)=>{this.setState(s, c)}} /> si vas a usar este truco, asegúrate de admitir la devolución de llamada.

    – Barkermn01

    10/04/2019 a las 14:50

  • Pasar una devolución de llamada para establecer el estado de los padres es una práctica realmente mala que podría generar problemas de mantenimiento. Rompe la encapsulación y hace que los componentes 2, 4 y 5 estén estrechamente acoplados al 1. Si sigue este camino, no podrá reutilizar ninguno de estos componentes secundarios en ningún otro lugar. Es mejor que tenga accesorios específicos para que los componentes secundarios puedan desencadenar eventos siempre que suceda algo, luego el componente principal manejaría ese evento correctamente.

    – Pato Loco

    4 de octubre de 2019 a las 13:51


  • @MarcelEnnix, ¿por qué los corchetes alrededor this.setState(p) ? Probé sin ellos y parece funcionar (soy muy nuevo en React)

    – Biganón

    10 de abril de 2020 a las 15:12

  • @Biganon Hmmm. Tienes razón. Lo siento por esos 2 caracteres adicionales 🙂 Tal vez sea porque me gustan mucho los corchetes rizados. Tengo una camiseta impresa con esta declaración ^^

    –Marcel Ennix

    12 de abril de 2020 a las 6:48

¿Como puedo actualizar el estado de los padres en React
Iván

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


class Parent extends React.Component {
  constructor(props) {
    super(props)

    this.handler = this.handler.bind(this)
  }

  handler() {
    this.setState({
      someVar: 'some value'
    })
  }

  render() {
    return <Child handler = {this.handler} />
  }
}

class Child extends React.Component {
  render() {
    return <Button onClick = {this.props.handler}/ >
  }
}

De esta forma, el hijo 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 según tengo entendido, 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.

  • ¿Por qué necesita this.handler = this.handler.bind(this) y no solo la función del controlador que establece el estado?

    – quimio78

    24 de febrero de 2017 a las 17:49

  • @ chemook78 en métodos de clases de ES6 React no se vinculan automáticamente a la clase. Entonces, si no agregamos this.handler = this.handler.bind(this) en constructor, this dentro de handler la función hará referencia al cierre de la función, no a la clase. Si no desea vincular todas sus funciones en el constructor, hay dos formas más de lidiar con esto usando funciones de flecha. Simplemente podría escribir el controlador de clics como onClick={()=> this.setState(...)}o puede usar inicializadores de propiedad junto con funciones de flecha como se describe aquí babeljs.io/blog/2015/06/07/react-on-es6-plus en “Funciones de flecha”

    – Iván

    24 de febrero de 2017 a las 20:54

  • He aquí un ejemplo de esto en acción: plnkr.co/edit/tGWecotomktae8zjS5yEr?p=preview

    – Tambor

    1 de junio de 2017 a las 2:03


  • Todo eso tiene sentido, ¿por qué e.preventDefault? y eso requiere jquery?

    – Vicente Buscarello

    3 de julio de 2017 a las 22:21

  • Pregunta rápida, ¿esto no permite la asignación de un estado local dentro del niño?

    – Este chico no puede ni siquiera

    2 mayo 2018 a las 17:29

¿Como puedo actualizar el estado de los padres en React
romano

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

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

  • ¡Este es bueno! podrías explicar esta pieza: <ChildB handleToUpdate = {handleToUpdate.bind(this)} /> ¿Por qué tuvo que atar de nuevo?

    – danés

    14/10/2017 a las 13:46


  • @Dane: debe vincular el contexto de esto para que sea el padre, de modo que cuando this se llama dentro del niño, this se refiere al estado de los padres y no al del niño. ¡Este es el cierre en su máxima expresión!

    – Casey

    14/03/2018 a las 21:37

  • @Casey, pero ¿no estamos haciendo eso en el constructor? ¿Y eso no es suficiente?

    – danés

    15 de marzo de 2018 a las 4:18

  • ¡Tienes toda la razón! Me lo perdí. Sí, si ya lo hiciste en el constructor, ¡entonces estás listo!

    – Casey

    15 de marzo de 2018 a las 4:20

  • ¡Eres una leyenda compañero! Esto mantendrá los componentes muy bien autocontenidos sin tener que verse obligados a crear componentes principales para manejar los intercambios de estado.

    – adamj

    1 de julio de 2018 a las 0:47

Así es como podemos hacerlo con el nuevo useState gancho. Método: pase la función de cambio de estado como accesorio al componente secundario y haga lo que quiera con la función

import React, {useState} from 'react';

const ParentComponent = () => {
  const[state, setState]=useState('');
  
  return(
    <ChildConmponent stateChanger={setState} />
  )
}


const ChildConmponent = ({stateChanger, ...rest}) => {
  return(
    <button onClick={() => stateChanger('New data')}></button>
  )
}

  • Buen ejemplo moderno

    – mylesthe.dev

    16 de febrero de 2021 a las 22:15

  • Gracias. @mylesthe.dev

    – moshfiqrony

    8 oct 2021 a las 18:22

  • por alguna extraña razón, obtengo stateChanger (setState) no es una función. Usé el mismo código exacto

    – Shabarinath

    13 de febrero a las 13:45

  • Los accesorios que pasó a stateChanger no son una función. O has hecho algo malo. Comparte tu código.

    – moshfiqrony

    13 de febrero a las 15:59

Quiero agradecer a la respuesta más votada por darme la idea de mi propio problema, básicamente, la variación 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.

1646756352 661 ¿Como puedo actualizar el estado de los padres en React
Estilos mate

Me gusta la respuesta con respecto a pasar funciones. Es una técnica muy práctica.

Por otro lado, también puede lograr esto usando pub/sub o usando una variante, un despachador, como Flujo lo hace. La teoría es súper simple. Haga que el componente 5 envíe un mensaje que el componente 3 está escuchando. Luego, el componente 3 actualiza su estado, lo que activa la nueva representación. Esto requiere componentes con estado, que, según su punto de vista, pueden o no ser un antipatrón. Estoy en contra de ellos personalmente y preferiría que otra cosa esté escuchando los despachos y los cambios de 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 de despachador con Flux son muy simples. Simplemente registra las devoluciones de llamadas y las invoca cuando se produce un envío, pasando por los contenidos del envío (en el conciso ejemplo anterior no hay payload con el envío, 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 tiene más sentido para usted.

  • Mis componentes de Reacts se “ejecutan” en el navegador como en un tutorial oficial (facebook.github.io/react/docs/tutorial.html) Intenté incluir Flux con browserify, pero el navegador dice que Dispatcher no se encuentra 🙁

    – Wojciech Kulma

    21 de febrero de 2016 a las 20:06

  • La sintaxis que usé fue la sintaxis del módulo ES2016 que requiere transpilación (uso Babelpero hay otros, los babelificar transform se puede usar con browserify), se transpila a var Dispatcher = require( 'flux' ).Dispatcher

    – Estilos mate

    22 de febrero de 2016 a las 8:44

1646756352 918 ¿Como puedo actualizar el estado de los padres en React
Pedro Mortensen

Encontré la siguiente solución de trabajo para pasar el argumento de la función onClick del componente secundario al componente principal con un parámetro:

Clase de 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>
    )
} }

  • Mis componentes de Reacts se “ejecutan” en el navegador como en un tutorial oficial (facebook.github.io/react/docs/tutorial.html) Intenté incluir Flux con browserify, pero el navegador dice que Dispatcher no se encuentra 🙁

    – Wojciech Kulma

    21 de febrero de 2016 a las 20:06

  • La sintaxis que usé fue la sintaxis del módulo ES2016 que requiere transpilación (uso Babelpero hay otros, los babelificar transform se puede usar con browserify), se transpila a var Dispatcher = require( 'flux' ).Dispatcher

    – Estilos mate

    22 de febrero de 2016 a las 8:44

1646756352 918 ¿Como puedo actualizar el estado de los padres en React
Pedro Mortensen

Siempre que necesite comunicarse entre un niño y el padre en cualquier nivel inferior, entonces es mejor hacer uso de contexto. En el componente padre, defina el contexto que puede ser invocado por el hijo, como por ejemplo:

En el componente padre, 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 secundario (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>
)}

Puede encontrar el proyecto Demo en este repositorio de GitHub.

  • No puedo entender esta respuesta, ¿puedes explicar más al respecto?

    –Ashish Kamble

    12 de junio de 2019 a las 4:34

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad