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

tor*_*eff 74 javascript reactjs

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

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

儿童组成部分:

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}/>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

我需要从Parent Component 更改Child Component的打开状态,或者在单击Parent Component中的Button时从Parent Component 调用Child Component的toggleMenu()

Oli*_*ssé 105

应该在父组件中管理状态.您可以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}/>
      );
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我们如何更改子组件中的打开状态? (3认同)
  • 这样,整个父组件就会被重新渲染,从而降低了效率。您能否告诉我们,只有子组件会更新其状态或道具(意味着重新渲染)而不重新渲染父组件的任何方式。 (3认同)
  • 是的,这本质上就是react-classnames包的作用,但它也允许你总是应用一组类名,并有条件地应用其他类名.像这样:`classNames({foo:true,bar:this.props.open});`// =>'foo'当this.props.open = false时,'foo bar'当this.props.open = true时. (2认同)

mig*_*ano 17

父组件可以管理将prop传递给子级的子状态,子级使用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} />
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 在反应 16 中使用 getDerivedStateFromProps (2认同)
  • 在这种情况下,子组件内的toggleMenu()状态变化将如何到达父组件?想象一下我关闭抽屉,父组件如何知道它已关闭? (2认同)

Jai*_*son 14

上面的答案对我来说部分正确,但在我的场景中,我想将值设置为一个状态,因为我已经使用该值来显示/切换模态.所以我用过如下.希望它会帮助某人.

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>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

参考 - https://github.com/kriasoft/react-starter-kit/issues/909#issuecomment-252969542

  • 这实际上是 React 中不鼓励的模式,因为它颠倒了信息流。如果 React 有一个 zen,那么它就是_data down,actions up_。这个概念使得 React 应用程序变得如此容易推理。命令式句柄可能很有用,但应谨慎使用并经过深思熟虑。它们不应该成为切换可见性等的首选解决方案。 (3认同)
  • 这就是我想要的,但我想知道为什么不直接使用 react refs?见[文档](https://reactjs.org/docs/refs-and-the-dom.html) (2认同)

Pra*_*mar 7

您可以使用 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>
    );
  }
}

Run Code Online (Sandbox Code Playgroud)

子组件


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



Run Code Online (Sandbox Code Playgroud)

  • 这是我找到的最好的答案,因为它不会重新渲染父组件。这是更快更好的练习! (6认同)
  • 是的,这实际上也是满足我需求的最佳答案。这是非常干净的,我们应该赞成这个答案。 (2认同)
  • 这似乎不适用于功能组件。功能子组件的等效实现是什么样的? (2认同)