如何在反应中从父级激发孩子的功能?

时间:2019-05-14 19:07:54

标签: javascript reactjs

我的React应用程序包含三个组件。其中两个是子组件,另一个是父组件。我需要通过父组件将数据(projectId)从一个子组件传递给另一个子组件,并在接收到数据后触发一个函数。作为示例,我将ProjectId从ChildOne发送到Parent,然后将projectId从ParentOne发送到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>
       )
    }
}

4 个答案:

答案 0 :(得分: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>
       )
    }
}

案例2:

ChildTwo打算在projectId更改时对其内部的内容进行一些更改。然后,您可以使用componentDidUpdate挂钩来查看prop是否已更改并做出响应。

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

案例3

如果以上任何一种情况都不适合您,那么当projectId使用key属性更改时,您可以手动重新加载整个组件:

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

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

答案 1 :(得分: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>
       )
}



答案 2 :(得分:1)

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

您的函数无法从prop接收任何内容作为参数。

因此,您的函数应如下所示:

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

然后您应该像这样使用componentWillReceiveProps

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

这是我为解决您的问题而创建的工作代码和框示例: https://codesandbox.io/s/5v4rn7qnll

答案 3 :(得分:1)

您可能应该使用componentDidUpdate并附带条件,以检查state更改时是否需要更新sendOneId中的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>

相关问题