我的结构如下:
Component 1
 - |- Component 2
 - - |- Component 4
 - - -  |- Component 5
Component 3
组件 3 应根据组件 5 的状态显示一些数据。
由于 props 是不可变的,我不能简单地将它的状态保存在组件 1 中并转发它,对吗?是的,我读过Redux,但我不想使用它。我希望可以通过react来解决它。我错了吗?
我的结构如下:
Component 1
 - |- Component 2
 - - |- Component 4
 - - -  |- Component 5
Component 3
组件 3 应根据组件 5 的状态显示一些数据。
由于 props 是不可变的,我不能简单地将它的状态保存在组件 1 中并转发它,对吗?是的,我读过Redux,但我不想使用它。我希望可以通过react来解决它。我错了吗?
对于子父通信,您应该传递一个函数来设置从父到子的状态,就像这样
class Parent extends React.Component {
  constructor(props) {
    super(props)
    this.handler = this.handler.bind(this)
  }
  handler() {
    this.setState({
      someVar: 'some value'
    })
  }
  render() {
    return <Child handler = {this.handler} />
  }
}
class Child extends React.Component {
  render() {
    return <Button onClick = {this.props.handler}/ >
  }
}
通过这种方式,子进程可以通过调用通过 props 传递的函数来更新父进程的状态。
但是您必须重新考虑组件的结构,因为据我了解,组件 5 和 3 不相关。
一种可能的解决方案是将它们包装在更高级别的组件中,该组件将包含组件 1 和 3 的状态。该组件将通过 props 设置较低级别的状态。
我发现以下工作解决方案将 onClick 函数参数从子组件传递给父组件:
传递方法()的版本
//ChildB component
class ChildB extends React.Component {
    render() {
        var handleToUpdate = this.props.handleToUpdate;
        return (<div><button onClick={() => handleToUpdate('someVar')}>
            Push me
          </button>
        </div>)
    }
}
//ParentA component
class ParentA extends React.Component {
    constructor(props) {
        super(props);
        var handleToUpdate = this.handleToUpdate.bind(this);
        var arg1 = '';
    }
    handleToUpdate(someArg){
        alert('We pass argument from Child to Parent: ' + someArg);
        this.setState({arg1:someArg});
    }
    render() {
        var handleToUpdate = this.handleToUpdate;
        return (<div>
                    <ChildB handleToUpdate = {handleToUpdate.bind(this)} /></div>)
    }
}
if(document.querySelector("#demo")){
    ReactDOM.render(
        <ParentA />,
        document.querySelector("#demo")
    );
}
传递箭头函数的版本
//ChildB component
class ChildB extends React.Component {
    render() {
        var handleToUpdate = this.props.handleToUpdate;
        return (<div>
          <button onClick={() => handleToUpdate('someVar')}>
            Push me
          </button>
        </div>)
    }
}
//ParentA component
class ParentA extends React.Component {
    constructor(props) {
        super(props);
    }
    handleToUpdate = (someArg) => {
            alert('We pass argument from Child to Parent: ' + someArg);
    }
    render() {
        return (<div>
            <ChildB handleToUpdate = {this.handleToUpdate} /></div>)
    }
}
if(document.querySelector("#demo")){
    ReactDOM.render(
        <ParentA />,
        document.querySelector("#demo")
    );
}
这就是我们如何使用新useState钩子来做到这一点。方法 - 将状态更改器函数作为props传递给子组件,并对该函数执行任何您想做的事情
import React, {useState} from 'react';
const ParentComponent = () => {
  const[state, setState]=useState('');
  
  return(
    <ChildConmponent stateChanger={setState} />
  )
}
const ChildConmponent = ({stateChanger, ...rest}) => {
  return(
    <button onClick={() => stateChanger('New data')}></button>
  )
}
我要感谢最受好评的答案给了我我自己的问题的想法,基本上是它与箭头函数的变化和从子组件传递参数:
 class Parent extends React.Component {
  constructor(props) {
    super(props)
    // without bind, replaced by arrow func below
  }
  handler = (val) => {
    this.setState({
      someVar: val
    })
  }
  render() {
    return <Child handler = {this.handler} />
  }
}
class Child extends React.Component {
  render() {
    return <Button onClick = {() => this.props.handler('the passing value')}/ >
  }
}
希望它可以帮助某人。
我喜欢关于传递函数的答案。这是一个非常方便的技术。
另一方面,您也可以使用 pub/sub 或使用变体、调度程序来实现这一点,就像Flux一样。理论超级简单。让组件 5 发送组件 3 正在侦听的消息。然后组件 3 更新其触发重新渲染的状态。这需要有状态的组件,根据您的观点,它可能是也可能不是反模式。我个人反对他们,宁愿其他东西从上到下监听调度和更改状态(Redux 这样做,但它增加了额外的术语)。
import { Dispatcher } from 'flux'
import { Component } from 'React'
const dispatcher = new Dispatcher()
// Component 3
// Some methods, such as constructor, omitted for brevity
class StatefulParent extends Component {
  state = {
    text: 'foo'
  } 
  componentDidMount() {
    dispatcher.register( dispatch => {
      if ( dispatch.type === 'change' ) {
        this.setState({ text: 'bar' })
      }
    }
  }
  render() {
    return <h1>{ this.state.text }</h1>
  }
}
// Click handler
const onClick = event => {
  dispatcher.dispatch({
    type: 'change'
  })
}
// Component 5 in your example
const StatelessChild = props => {
  return <button onClick={ onClick }>Click me</button> 
}
与 Flux 捆绑的调度程序非常简单。它只是注册回调并在任何调度发生时调用它们,传递调度上的内容(在上面的简洁示例中payload,调度没有,只是一个消息 ID)。如果这对您更有意义,您可以非常轻松地将其调整为传统的发布/订阅(例如,使用来自事件的 EventEmitter 或其他版本)。