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?


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

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

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


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.


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


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.