如何在React中从父组件调用子组件的函数?

3
我的 React 应用有三个组件,其中两个是子组件,另一个是父组件。我需要通过父组件将一个数据(projectId)从一个子组件传递到另一个子组件,并在接收到数据后触发一个函数。例如,我正在从 ChildOne 发送 projectId 到 Parent,然后从 Parent 发送 projectId 到 ChildTwo。ChildTwo 有一个名为 setProject(projectId) 的函数,一旦接收到 projectId,我需要触发该函数。 问题在于,我无法通过单击 ChildOne 中的按钮来触发 ChildTwo 中的 getProjectId 函数。我还尝试过 componentDidMount 和 componentWillReceiveProps,但对我没有用。 我该怎么做?

以下是我的尝试:

ChildOne:

class ChildOne extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
          projectId: 3,
        };
    }

    sendProjectId = (projectId) => {
       this.props.sendId(projectId)
    }

    render() {
       return(
         <button onClick={() => this.sendProjectId(this.state.projectId)}>
            Click
         </button>
       )
    }
}

父级:

class Parent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
          projectId: '',
        };
    }

    getId = (proId) => {
       this.setState({
          projectId : proId
       })
    }

    render() {
       return(
         <div>
           <CildOne sendId={this.getId} />

           <CildTwo sendOneId={this.state.projectId} />
         </div>
       )
    }
}

ChildTwo:

class ChildTwo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
          projectId: '',
        };
    }

    getProjectId = (this.props.sendOneId) => {
       //Do something with this.props.sendOneId
    }

    render() {
       return(
         <div></div>
       )
    }
}

你在ChildTwo中打算如何使用this.props.sendOneId?解决方案将取决于你的用例。 - Deepak
我认为在你的情况下 componentWillReceiveProps 应该可以正常工作。 - Vishal
"componentWillReceiveProps"已被弃用。 - Andy
4个回答

3

这取决于ChildTwo想要通过数据实现什么目的。

情况1:

ChildTwo希望获取相应projectId的一些数据,并在组件中显示。那么,您可以轻松地在父组件中获取这些数据,并将其作为props传递下来。

class Parent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
          projectId: '',
          dataForChildTwo: null,
        };
    }

    getId = (proId) => {
       this.setState({
          projectId : proId,
          dataForChildTwo: fetchData(proId)
       })
    }

    render() {
       return(
         <div>
           <CildOne sendId={this.getId} />

           <CildTwo data={this.state.dataForChildTwo} />
         </div>
       )
    }
}

案例二:

ChildTwo想在projectId发生变化时对其中的某些内容进行修改。那么,您可以使用componentDidUpdate钩子来检查属性是否更改并做出响应。

class ChildTwo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
          projectId: '',
        };
    }

    getProjectId = (this.props.sendOneId) => {
       //Do something with this.props.sendOneId
    }

    componentDidUpdate(prevProps) {
      if(this.props.projectId!==prevProps.projectId) {
        // do something
      }
    }

    render() {
       return(
         <div></div>
       )
    }
}

案例三:

如果以上情况都不适用于您,您可以使用 key 属性在 projectId 更改时手动重新加载完整组件:

<CildTwo key={this.state.projectId} sendOneId={this.state.projectId} />

注意:这将不必要地重新加载整个组件。

谢谢!你的Case 3答案解决了我的问题! - David Johns

1
如果您想设置一些状态,可以尝试使用功能组件或钩子。
function ChildOne(props) {
  const [projectId, setProjectId] = useState(3);
  function sendProjectId(data){
       props.sendId(projectId)
    }
   return(
         <button onClick={() => sendProjectId(projectId)}>
            Click
         </button>
       )
}



function ChildTwo(props) {
  const [state, setState] = useState('')
  function getProjectId(data) {
       //Do something with this.props.sendOneId
       console.log(`data here ${data}`)
       return false;
    }
    getProjectId(props.sendOneId)
  return (
    <div>
    </div>
  )
}


function Parent(){
   const [projectId, setProjectId] = useState('');
   function getId(proId) {
     setProjectId(proId)
   }
   return(
         <div>
           <ChildOne sendId={getId} />

           <ChildTwo sendOneId={projectId} />
         </div>
       )
}




1

您在ChildTwo组件的getProjectId函数中犯了一个错误。

您的函数不能从prop中接收任何参数。

因此,您的函数应该像这样:

getProjectId = (sendOneId) => {
   //Do something with this.props.sendOneId
}

那么你应该像这样使用 componentWillReceiveProps

componentWillReceiveProps(nextProps) {
  if (this.props.sendOneId !== nextProps.sendOneId) {
    this.getProjectId(nextProps.sendOneId);
  }
}

这里是我创建的一个可工作的Codesandbox示例,用于解决你的问题:https://codesandbox.io/s/5v4rn7qnll


componentWillReceiveProps已被弃用,并且在v17中将停止工作 - Andy
@Andy 我知道 componentWillReceiveProps 已经过时了。但是 OP 提到他尝试了 componentWillReceiveProps 并且没有成功。这意味着他现在可以安全地使用它。 - Vishal

1
你应该使用 componentDidUpdate 并添加一个条件来检查当 sendOneId 改变时是否需要更新 state 中的 projectId。然后可以使用 setState 的回调函数来调用 getProjectId
componentDidUpdate() {
  const { projectId: currentProjectId } = this.state;
  const { sendOneId: projectId } = this.props;
  if (projectId !== currentProjectId) {
    this.setState({ projectId }, () => this.getProjectId());
  }
}

完整工作示例:

class ChildOne extends React.Component {
    
  constructor(props) {
    super(props);
      this.state = {
        projectId: 3,
      };
    }

    sendProjectId = (projectId) => {
      this.props.sendId(projectId)
    }

    render() {
      return (
        <button onClick={() => this.sendProjectId(this.state.projectId)}>
          Click
        </button>
      );
    }
}

class Parent extends React.Component {
  
  constructor(props) {
    super(props);
    this.state = {
      projectId: '',
    };
  }

  getId = (projectId) => {
    this.setState({ projectId });
  }

  render() {
    return (
      <div>
        <ChildOne sendId={this.getId} />
        <ChildTwo sendOneId={this.state.projectId} />
      </div>
    )
  }

}

class ChildTwo extends React.Component {

    constructor(props) {
      super(props);
      this.state = {
        projectId: '',
      };
    }

    componentDidUpdate() {
      const { projectId: currentProjectId } = this.state;
      const { sendOneId: projectId } = this.props;
      if (projectId !== currentProjectId) {
        this.setState({ projectId }, () => this.getProjectId());
      }
    }

    getProjectId = () => {
      console.log(this.state.projectId);
    }

    render() {
      return (
        <div></div>
      );
    }
}

ReactDOM.render(
  <Parent />,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="container"></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接