React js change l'état du composant enfant du composant parent

94

J'ai deux composants: Composant parent à partir duquel je veux changer l'état du composant enfant:

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

Et composant enfant :

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}/>
    );
  }
}

Je dois soit changer l' état ouvert du composant enfant à partir du composant parent, soit appeler toggleMenu () du composant enfant à partir du composant parent lorsque l'utilisateur clique sur le bouton dans le composant parent?

torayeff
la source
Peut-être que vous pouvez tenir une référence enfant dans le parent, et changer l'état de l'enfant explicitement, Voir ce document
Chaojun Zhong

Réponses:

122

L'état doit être géré dans le composant parent. Vous pouvez transférer la openvaleur vers le composant enfant en ajoutant une propriété.

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}/>
      );
    }
}
Olivier Boissé
la source
Cela peut-il être utilisé pour contrôler une propriété css telle que «affichage»? comme dans, si mon prop 'open' contient soit 'none' ou 'inline-block', le prop d'affichage css sera-t-il mis à jour?
deusofnull
2
Oui, c'est essentiellement ce que fait le package react-classnames, mais il vous permet également de toujours appliquer un ensemble de noms de classe et d'en appliquer d'autres de manière conditionnelle. Comme ceci: classNames({ foo: true, bar: this.props.open });// => 'foo' quand this.props.open = false et 'foo bar' quand this.props.open = true.
deusofnull
1
Comment pouvons-nous changer l'état ouvert dans le composant enfant?
Priyabrata Atha
1
vous pouvez ajouter une propriété toggleau ChildComponent <ChildComponent open={this.state.open} toggle={this.toggleChildMenu.bind(this)} />et appeler this.props.toggle()le composant enfant
Olivier Boissé
1
Je ne comprends pas, vous pouvez l'appeler où vous voulez dans le composant enfant dès que vous avez spécifié cette propriété lors de la déclaration de ChildComponent-><ChildComponent toggle={this.toggleChildMenu.bind(this)} />
Olivier Boissé
25

Le composant parent peut gérer l'état de l'enfant en passant un accessoire à l'enfant et l'enfant convertit cet accessoire en état à l'aide de 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} />
  }
}
Miguel Savignano
la source
1
dans react 16, utilisez getDerivedStateFromProps
Fadi Abo Msalam
1
@FadiAboMsalam J'utilise la version 16.7.0 de react avec la version 16.7.18 de @ Types / react. Au moins du côté de TypeScript, il ne semble pas y en avoir getDerivedStateFromProps(). Cependant, la réponse de Miguel suggérant d'utiliser componentWillReceiveProps(props)est disponible et a fonctionné comme un charme dans mon environnement.
Manfred
Dans ce cas, comment le changement d'état toggleMenu () à l'intérieur du composant enfant atteindrait-il le parent? Imaginez que je ferme le tiroir, comment le composant parent saurait-il qu'il a été fermé?
norman123123
20

La réponse ci-dessus est partiellement correcte pour moi, mais dans mon scénario, je souhaite définir la valeur sur un état, car j'ai utilisé la valeur pour afficher / basculer un modal. J'ai donc utilisé comme ci-dessous. J'espère que cela aidera quelqu'un.

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>
    );
  }
}

Référence - https://github.com/kriasoft/react-starter-kit/issues/909#issuecomment-252969542

Jaison
la source
2
C'est ce que je veux, mais je me demande pourquoi ne pas simplement utiliser des références de réaction? voir doc
Chaojun Zhong
Que fait l'hélice onRef?
norman123123
1

Vous pouvez envoyer une prop du parent et l'utiliser dans le composant enfant afin de baser les changements d'état de l'enfant sur les modifications de prop envoyées et vous pouvez gérer cela en utilisant getDerivedStateFromProps dans le composant enfant.

Juba Fourali
la source
1

Vous pouvez utiliser createRef pour modifier l'état du composant enfant à partir du composant parent. Voici toutes les étapes.

  1. Créez une méthode pour modifier l'état dans le composant enfant.

    2 - Créez une référence pour le composant enfant dans le composant parent à l'aide de React.createRef ().

    3 - Attachez la référence au composant enfant en utilisant ref = {}.

    4 - Appelez la méthode du composant enfant en utilisant this.yor-reference.current.method.

Composant parent


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>
    );
  }
}

Composant enfant


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}/>
    );
  }
}


Pranay kumar
la source