我的结构如下所示:

Component 1

 - |- Component 2


 - - |- Component 4


 - - -  |- Component 5

Component 3

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

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


当前回答

父组件

 function Parent() {
        const [value, setValue] = React.useState("");

        function handleChange(newValue) {
          setValue(newValue);
        }

        // We pass a callback to Child
        return <Child value={value} onChange={handleChange} />;
    }

子组件

    function Child(props) {
         function handleChange(event) {
             // Here, we invoke the callback with the new value
             props.onChange(event.target.value);
         }
  
         return <input value={props.value} onChange={handleChange} />
    }

其他回答

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

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或其他版本)。

我找到了以下工作解决方案,将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")
    );
}

看看JSFiddle

使用传递箭头函数的版本

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

看看JSFiddle

你可以通过将父对象的引用传递给子对象来实现,如下所示:

在A.js中有一个带有updateAState方法的父组件a 在B.js中有一个子组件B 有一个包装器函数,在C.js中呈现< a ><B></B></ a > 在C.js中,你可以像下面这样使用useRef:

import React, {useRef} from " React "; 导出默认函数C() { const parentARef = useRef(); const handleChildBClick = () => parentARef.current.updateAState(); 回报( < ref = {parentARef} > < B onClick = {handleChildBClick} > < / B > < / > ); }

指南参考:https://stackoverflow.com/a/56496607/1770571

只需通过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;

我已经多次使用这个页面的顶级答案,但在学习React的时候,我发现了一个更好的方法,没有绑定,也没有道具内的内联函数。

看看这里:

class Parent extends React.Component {

  constructor() {
    super();
    this.state = {
      someVar: value
    }
  }

  handleChange = (someValue) => {
    this.setState({someVar: someValue})
  }

  render() {
    return <Child handler={this.handleChange} />
  }

}

export const Child = ({handler}) => {
  return <Button onClick={handler} />
}

键在一个箭头函数中:

handleChange = (someValue) => {
  this.setState({someVar: someValue})
}

你可以在这里阅读更多。