ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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()?

也许您可以在父项中保存子项引用,并显式更改子项的状态,请参阅此doc

p
pwolaq

状态应该在父组件中管理。您可以通过添加属性将 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}/>
      );
    }
}

是的,这基本上就是 react-classnames 包所做的,但它也允许您始终应用一组类名,并有条件地应用其他类名。像这样:classNames({ foo: true, bar: this.props.open }); // =>当 this.props.open = false 时为“foo”,当 this.props.open = true 时为“foo bar”。
我们如何更改子组件中的打开状态?
您可以将属性 toggle 添加到 ChildComponent <ChildComponent open={this.state.open} toggle={this.toggleChildMenu.bind(this)} /> 并在子组件中调用 this.props.toggle()
我不明白,只要在声明 ChildComponent -> 时指定了此属性,您就可以在子组件中的任何位置调用它<ChildComponent toggle={this.toggleChildMenu.bind(this)} />
通过这种方式,整个 Parent 组件被重新渲染,从而降低了效率。你能告诉我只有子组件会更新其状态或道具(意味着重新渲染)而不重新渲染父组件的任何方式吗?
m
miguel savignano

父组件可以管理子状态,将 prop 传递给子组件,子组件使用 componentWillReceiveProps 将此 prop 转换为状态。

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

在反应 16 中使用 getDerivedStateFromProps
@FadiAboMsalam 我将 React 版本 16.7.0 与 @Types/react 版本 16.7.18 一起使用。至少在 TypeScript 方面似乎没有 getDerivedStateFromProps()。但是,Miguel 建议使用 componentWillReceiveProps(props) 的答案是可用的,并且在我的环境中就像一个魅力。
在这种情况下,子组件内的 toggleMenu() 状态更改将如何到达父组件?想象一下我关闭了抽屉,父组件怎么知道它已经关闭了?
J
Jaison James

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

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


这就是我想要的,但我想知道为什么不直接使用 react refs?见doc
onRef 道具有什么作用?
这实际上是一种不鼓励的反应模式,因为它会逆转信息流。如果反应只有一个禅宗,那就是数据下降,行动上升。这就是让 React 应用程序如此易于推理的概念。命令式句柄可能很有用,但应谨慎使用且经过深思熟虑。它们不应该是例如切换可见性的首选解决方案。
E
Evandro Pomatti

您可以使用 createRef 从父组件更改子组件的状态。这是所有步骤。

创建一个方法来更改子组件中的状态。使用 React.createRef() 在父组件中为子组件创建引用。使用 ref={} 将引用附加到子组件。使用 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}/>
    );
  }
}




这是我找到的最佳答案,因为它不会重新渲染父组件。这是更快更好的练习!
是的,这实际上也是满足我需求的最佳答案。这很干净,我们应该赞成这个答案。
在父级上,我必须使用处理程序方法而不是直接调用子级。然后它起作用了。
I
Idrees

如果您使用的是功能组件。您可以通过以下方式实现:

const ParentComponent = () => {
   const [isOpen, setIsOpen] = useState(false)

   toggleChildMenu() {
      setIsOpen(prevValue => !prevValue)
   }

   return (
     <div>
       <button onClick={toggleChildMenu}>
         Toggle Menu from Parent
       </button>
       <Child open={isOpen} />
     </div>
   );
}



const Child = ({open}) => {
  return (
    <Drawer open={open}/>
  );
}

在这种情况下,孩子如何控制 open?如果孩子说有一个关闭抽屉的按钮,这是怎么回事?
J
Juba Fourali

您可以从父组件发送一个 prop 并在子组件中使用它,这样您就可以将子组件的状态更改基于发送的 prop 更改,您可以通过在子组件中使用 getDerivedStateFromProps 来处理这个问题。


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅