React js从父组件更改子组件的状态


94

我有两个组件: 父组件,我想从中更改子组件的状态:

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

Answers:


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

可以用来控制css属性(例如“ display”)吗?例如,如果我的道具“ open”包含“ none”或“ inline-block”,css显示道具会更新吗?
deusofnull

2
是的,这本质上是react-classnames包的功能,但是它还允许您始终应用一组类名,并有条件地应用其他类名。像这样: classNames({ foo: true, bar: this.props.open });// =>当this.props.open = false时为'foo',当this.props.open = true时为'foo bar'。
deusofnull

1
我们如何更改子组件的打开状态?
Priyabrata Atha

1
您可以将属性添加toggle到ChildComponent <ChildComponent open={this.state.open} toggle={this.toggleChildMenu.bind(this)} />并调用this.props.toggle()子组件
OlivierBoissé18年

1
我不明白,在声明ChildComponent-><ChildComponent toggle={this.toggleChildMenu.bind(this)} />
OlivierBoissé18年

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()。但是,Miguel的建议使用的答案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
这就是我想要的,但是我想知道为什么不只使用react refs?参见doc
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}/>
    );
  }
}


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.