React jsは子コンポーネントの状態を親コンポーネントから変更します


94

私は2つのコンポーネントを持っています: 子コンポーネントの状態を変更したい親コンポーネント

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

そして、子供コンポーネント

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

親コンポーネントのボタンがクリックされたときに、子コンポーネントの開いた状態を親コンポーネントから変更するか、親コンポーネントから子コンポーネントのtoggleMenu()を呼び出す必要がありますか?


おそらく、親で子参照を保持し、子の状態を明示的に変更できます。このドキュメントを
Chaojun Zhong

回答:


122

状態は親コンポーネントで管理する必要があります。openプロパティを追加することにより、値を子コンポーネントに転送できます。

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

これを使用して、「display」などのcssプロパティを制御できますか?のように、私の小道具 'open'に 'none'または 'inline-block'が含まれている場合、CSS表示小道具は更新されますか?
deusofnull 2017

2
ええ、それは基本的に、react-classnamesパッケージが行うことですが、クラス名のセットを常に適用し、他のものを条件付きで適用することもできます。このように: classNames({ foo: true, bar: this.props.open });// => 'foo'(this.props.open = falseの場合)および 'foo bar'(this.props.open = trueの場合)。
deusofnull 2017

1
子コンポーネントのオープン状態をどのように変更できますか?
Priyabrata Atha

1
toggleChildComponentにプロパティを追加し、子コンポーネント<ChildComponent open={this.state.open} toggle={this.toggleChildMenu.bind(this)} />を呼び出すことができthis.props.toggle()ます
OlivierBoissé

1
わかりません。子コンポーネントで宣言するときに、このプロパティを指定するとすぐに呼び出すことができますChildComponent-><ChildComponent toggle={this.toggleChildMenu.bind(this)} />
OlivierBoisséFeb

25

親コンポーネントは子の状態を管理して、プロップを子に渡し、子は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
反応16でgetDerivedStateFromPropsを使用
Fadi Abo Msalam

1
@FadiAboMsalam @ Types / reactバージョン16.7.18でreactバージョン16.7.0を使用しています。少なくともTypeScript側にはないようですgetDerivedStateFromProps()。しかし、使用することを提案するミゲルの回答componentWillReceiveProps(props)は入手可能であり、私の環境では魅力のように機能しました。
Manfred

この場合、子コンポーネント内のtoggleMenu()の状態変化はどのように親に到達しますか?引き出しを閉じたとしたら、親コンポーネントはそれが閉じられたことをどうやって知るのでしょうか?
norman123123

20

上記の答えは私には部分的に正しいですが、私のシナリオでは、モーダルの表示/切り替えに値を使用したため、値を状態に設定したいと思います。以下のように使っています。それが誰かを助けることを願っています。

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

リファレンス-https://github.com/kriasoft/react-starter-kit/issues/909#issuecomment-252969542


2
これは私が欲しいものですが、なぜ反応参照を使用しないのですか?ドキュメントを
Chaojun Zhong

onRefプロップは何をしますか?
norman123123

1

親から小道具を送信して子コンポーネントで使用できるため、送信された小道具の変更に基づいて子の状態変更を行い、子コンポーネントでgetDerivedStateFromPropsを使用してこれを処理できます。


1

createRefを使用して、子コンポーネントの状態を親コンポーネントから変更できます。ここにすべてのステップがあります。

  1. 子コンポーネントの状態を変更するメソッドを作成します。

    2-React.createRef()を使用して、親コンポーネントに子コンポーネントの参照を作成します。

    3-ref = {}を使用して子コンポーネントへの参照を添付します。

    4-this.yor-reference.current.methodを使用して子コンポーネントメソッドを呼び出します。

親コンポーネント


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

子コンポーネント


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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.