我的结构如下所示:

Component 1

 - |- Component 2


 - - |- Component 4


 - - -  |- Component 5

Component 3

组件3应该根据组件5的状态显示一些数据。

因为道具是不可变的,我不能简单地在组件1中保存它的状态并转发它,对吗?是的,我读过Redux,但我不想使用它。我希望只用react就能解决这个问题。我错了吗?


当前回答

我找到了以下工作解决方案,将onClick函数参数从子组件传递给带有参数的父组件:

父类:

class Parent extends React.Component {
constructor(props) {
    super(props)

    // Bind the this context to the handler function
    this.handler = this.handler.bind(this);

    // Set some state
    this.state = {
        messageShown: false
    };
}

// This method will be sent to the child component
handler(param1) {
console.log(param1);
    this.setState({
        messageShown: true
    });
}

// Render the child component and set the action property with the handler as value
render() {
    return <Child action={this.handler} />
}}

子类:

class Child extends React.Component {
render() {
    return (
        <div>
            {/* The button will execute the handler function set by the parent component */}
            <Button onClick={this.props.action.bind(this,param1)} />
        </div>
    )
} }

其他回答

我想感谢得到最多赞的回答,因为他给了我自己的问题的想法,基本上是用箭头函数和从子组件传递参数的变化:

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

希望它能帮助到别人。

对于子-父通信,您应该传递一个函数来设置从父到子的状态,如下所示


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设置较低级别的状态。

似乎我们只能将数据从父组件传递给子组件,因为React促进单向数据流,但为了让父组件在“子组件”中发生某些事情时更新自己,我们通常使用所谓的“回调函数”。

我们将父类中定义的函数作为“props”传递给子类 从子进程调用该函数,在父进程中触发它 组件。


class Parent extends React.Component {
  handler = (Value_Passed_From_SubChild) => {
    console.log("Parent got triggered when a grandchild button was clicked");
    console.log("Parent->Child->SubChild");
    console.log(Value_Passed_From_SubChild);
  }
  render() {
    return <Child handler = {this.handler} />
  }
}

class Child extends React.Component {
  render() {
    return <SubChild handler = {this.props.handler}/ >
  }
}

class SubChild extends React.Component {
  constructor(props){
   super(props);
   this.state = {
      somethingImp : [1,2,3,4]
   }
  }
  render() {
     return <button onClick = {this.props.handler(this.state.somethingImp)}>Clickme<button/>
  }
}
React.render(<Parent />,document.getElementById('app'));

 HTML
 ----
 <div id="app"></div>

在这个例子中,我们可以通过将函数传递给它的直接子函数来实现数据从子→子→父的传递。

我喜欢关于传递函数的答案。这是一个非常方便的技巧。

On the flip side you can also achieve this using pub/sub or using a variant, a dispatcher, as Flux does. The theory is super simple. Have component 5 dispatch a message which component 3 is listening for. Component 3 then updates its state which triggers the re-render. This requires stateful components, which, depending on your viewpoint, may or may not be an anti-pattern. I'm against them personally and would rather that something else is listening for dispatches and changes state from the very top-down (Redux does this, but it adds additional terminology).

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的调度程序捆绑非常简单。它只是简单地注册回调,并在任何分派发生时调用它们,传递分派上的内容(在上面的简洁示例中,分派没有有效负载,只有一个消息id)。如果对您更有意义的话,您可以很容易地将其调整为传统的pub/sub(例如,从事件中使用EventEmitter或其他版本)。

只需通过props将父组件的setState函数传递给子组件。

function ParentComp() {
  const [searchValue, setSearchValue] = useState("");
  return <SearchBox setSearchValue={setSearchValue} searchValue={searchValue} />;
}

然后在子组件中:

function SearchBox({ searchValue, setSearchValue }) {
  return (
        <input
          id="search-post"
          type="text"
          value={searchValue}
          onChange={(e) => setSearchValue(e.target.value)}
          placeholder="Search Blogs ..."
        />
    )
}

处理子组件点击的第二个例子:

// We've below function and component in parent component
const clickHandler = (val) => {
  alert(`httpRequest sent. \nValue Received: ${val}`);
};

// JSX
<HttpRequest clickHandler={clickHandler} />

这就是你如何从父组件中获取函数,然后传递一个值并通过它触发clickHandler。

function HttpRequest({ clickHandler }) {
  const [content, setContent] = useState("initialState");

  return (
    <button onClick={() => clickHandler(content)}>
      Send Request
    </button>
  );
}

export default HttpRequest;