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.