React js cambia lo stato del componente figlio dal componente genitore


94

Ho due componenti: Componente principale da cui voglio cambiare lo stato del componente figlio:

class ParentComponent extends Component {
  toggleChildMenu() {
    ?????????
  }
  render() {
    return (
      <div>
        <button onClick={toggleChildMenu.bind(this)}>
          Toggle Menu from Parent
        </button>
        <ChildComponent />
      </div>
    );
  }
}

E componente figlio :

class ChildComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false;
    }
  }

  toggleMenu() {
    this.setState({
      open: !this.state.open
    });
  }

  render() {
    return (
      <Drawer open={this.state.open}/>
    );
  }
}

Devo modificare lo stato di apertura del componente figlio dal componente padre o chiamare toggleMenu () del componente figlio dal componente padre quando si fa clic sul pulsante nel componente padre?


Forse puoi tenere un riferimento a un figlio nel genitore e cambiare lo stato del bambino in modo esplicito, vedi questo documento
Chaojun Zhong

Risposte:


122

Lo stato dovrebbe essere gestito nel componente padre. È possibile trasferire il openvalore al componente figlio aggiungendo una proprietà.

class ParentComponent extends Component {
   constructor(props) {
      super(props);
      this.state = {
        open: false
      };

      this.toggleChildMenu = this.toggleChildMenu.bind(this);
   }

   toggleChildMenu() {
      this.setState(state => ({
        open: !state.open
      }));
   }

   render() {
      return (
         <div>
           <button onClick={this.toggleChildMenu}>
              Toggle Menu from Parent
           </button>
           <ChildComponent open={this.state.open} />
         </div>
       );
    }
}

class ChildComponent extends Component {
    render() {
      return (
         <Drawer open={this.props.open}/>
      );
    }
}

Può essere usato per controllare una proprietà CSS come "display"? come in, se il mio prop "open" contiene "none" o "inline-block", il display css verrà aggiornato?
deusofnull

2
Sì, questo è essenzialmente ciò che fa il pacchetto react-classnames, ma ti consente anche di applicare sempre un insieme di nomi di classe e applicarne altri in modo condizionale. In questo modo: classNames({ foo: true, bar: this.props.open });// => 'foo' quando this.props.open = false e 'foo bar' quando this.props.open = true.
deusofnull

1
Come possiamo modificare lo stato aperto nel componente figlio?
Priyabrata Atha

1
puoi aggiungere una proprietà togglea ChildComponent <ChildComponent open={this.state.open} toggle={this.toggleChildMenu.bind(this)} />e chiamare this.props.toggle()il componente figlio
Olivier Boissé

1
Non capisco, puoi chiamarlo dove vuoi nel componente figlio non appena hai specificato questa proprietà quando dichiari ChildComponent-><ChildComponent toggle={this.toggleChildMenu.bind(this)} />
Olivier Boissé

25

Il componente genitore può gestire lo stato figlio passando un puntello al figlio e il figlio converte questo puntello nello stato utilizzando componentWillReceiveProps.

class ParentComponent extends Component {
  state = { drawerOpen: false }
  toggleChildMenu = () => {
    this.setState({ drawerOpen: !this.state.drawerOpen })
  }
  render() {
    return (
      <div>
        <button onClick={this.toggleChildMenu}>Toggle Menu from Parent</button>
        <ChildComponent drawerOpen={this.state.drawerOpen} />
      </div>
    )
  }
}

class ChildComponent extends Component {
  constructor(props) {
    super(props)
    this.state = {
      open: false
    }
  }

  componentWillReceiveProps(props) {
    this.setState({ open: props.drawerOpen })
  }

  toggleMenu() {
    this.setState({
      open: !this.state.open
    })
  }

  render() {
    return <Drawer open={this.state.open} />
  }
}

1
nella reazione 16 usa getDerivedStateFromProps
Fadi Abo Msalam

1
@FadiAboMsalam Sto usando la versione 16.7.0 di React con la versione 16.7.18 di @ Types / React. Almeno sul lato TypeScript non sembra esserci getDerivedStateFromProps(). Tuttavia, la risposta di Miguel che suggerisce di usare componentWillReceiveProps(props)è disponibile e ha funzionato come un incantesimo nel mio ambiente.
Manfred

In questo caso, come cambierebbe lo stato toggleMenu () all'interno del componente figlio raggiungere il genitore? Immagina di chiudere il cassetto, come farebbe il componente genitore a sapere che è stato chiuso?
norman123123

20

La risposta sopra è parzialmente corretta per me, ma nel mio scenario, voglio impostare il valore su uno stato, perché ho usato il valore per mostrare / attivare un modale. Quindi ho usato come di seguito. Spero che possa aiutare qualcuno.

class Child extends React.Component {
  state = {
    visible:false
  };

  handleCancel = (e) => {
      e.preventDefault();
      this.setState({ visible: false });
  };

  componentDidMount() {
    this.props.onRef(this)
  }

  componentWillUnmount() {
    this.props.onRef(undefined)
  }

  method() {
    this.setState({ visible: true });
  }

  render() {
    return (<Modal title="My title?" visible={this.state.visible} onCancel={this.handleCancel}>
      {"Content"}
    </Modal>)
  }
}

class Parent extends React.Component {
  onClick = () => {
    this.child.method() // do stuff
  }
  render() {
    return (
      <div>
        <Child onRef={ref => (this.child = ref)} />
        <button onClick={this.onClick}>Child.method()</button>
      </div>
    );
  }
}

Riferimento: https://github.com/kriasoft/react-starter-kit/issues/909#issuecomment-252969542


2
Questo è quello che voglio, ma mi chiedo perché non usare solo React Refs? vedi doc
Chaojun Zhong

Cosa fa l'elica onRef?
norman123123

1

Puoi inviare un oggetto di scena dal genitore e usarlo nel componente figlio in modo da basare le modifiche di stato del bambino sui cambiamenti di sostegno inviati e puoi gestirlo utilizzando getDerivedStateFromProps nel componente figlio.


1

È possibile utilizzare createRef per modificare lo stato del componente figlio dal componente padre. Ecco tutti i passaggi.

  1. Crea un metodo per modificare lo stato nel componente figlio.

    2 - Crea un riferimento per il componente figlio nel componente genitore usando React.createRef ().

    3 - Allega il riferimento al componente figlio utilizzando ref = {}.

    4 - Chiama il metodo del componente figlio usando this.yor-reference.current.method.

Componente genitore


class ParentComponent extends Component {
constructor()
{
this.changeChild=React.createRef()
}
  render() {
    return (
      <div>
        <button onClick={this.changeChild.current.toggleMenu()}>
          Toggle Menu from Parent
        </button>
        <ChildComponent ref={this.changeChild} />
      </div>
    );
  }
}

Componente figlio


class ChildComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false;
    }
  }

  toggleMenu=() => {
    this.setState({
      open: !this.state.open
    });
  }

  render() {
    return (
      <Drawer open={this.state.open}/>
    );
  }
}


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.