繁体   English   中英

React - 从“兄弟”组件调用 function

[英]React - Call function from 'sibling' component

这是我当前的 model,请查看

import component 1 & 2 

export default class App extends Component {  
  render() {    
    return (

        <Component1/>       
        <Component2/>

    );
  }
}

在组件 1 中,我有一个 function:运行此 function 后的 pushData(),我想在组件 2 上使用 fetchData() 执行下一步,但我找不到从 1 引用 2 的方法,因为它们不是父级-孩子?!

这可以通过多种方式完成,考虑到上面共享的代码具有基于 Class 的实现,我建议采用以下解决方案。

  • 首先传递一个 function 给 Component1,命名为dataPushed
  • 其次,在parent中创建一个state变量,命名为dataPushed ,初始化为false。
  • 第三次从parent传递一个function和一个state变量给Component2,分别命名为dataFetchedfetchData

现在 Component1 将拥有自己的 function 来推送数据,我们称其为 function pushData 一旦推送数据的逻辑结束,调用传递的 prop function dataPushed 此道具将使用当前状态更新父级 state,即数据已推送,并将 state 变量设置为 true。

现在这个state这个变量已经传给了Component2,在Component2中使用ComponentDidUpdate。我们可以知道从Component1传来的dataPush的state,如果为真,就可以调用Component2内部的function来获取数据。

获取数据后,立即调用传递给此 Component2 的 prop 让父级知道已获取最新数据,并将 dataPushed 的父级变量 state 设置为 false。

忽略 function 和使用的变量名,随意使用你的。

我用代码创建了一个沙箱,

https://codesandbox.io/s/affectionate-forest-5kc68?file=/src/App.js

我希望这能解决你的问题。 如果您仍然对上述任何解释感到困惑或不清楚,请告诉我。

从架构上讲,您尝试做的不是一个好主意。

例如,如果您更改具有您要使用的 function 的组件,您需要记住更新使用此 function 的任何依赖项。这变得难以维护。

React 道具实际上使使用依赖注入模式解决这个问题变得非常容易。 如果你不熟悉依赖注入,它本质上意味着依赖是自上而下的,需要这些依赖的组件不知道这个依赖在哪里,也不会出去获取它们。 它只是获取传入的依赖项。

您可以将 function 提升一个级别并让它存在于父组件中,而不是尝试使用存在于同级组件中的方法。 与 state 相同。

想象一下这位家长:

class Container extends React.Component {
  state = {
    counter: 0
  };

  reallyCoolFunction = () => {
    this.setState({ counter: this.state.counter + 1 });
  };

  render() {
    return (
      <>
        <Cool
          counter={this.state.counter}
          doCoolThing={this.reallyCoolFunction}
        />
        <Wannabe doCoolThing={this.reallyCoolFunction} />
      </>
    );
  }
}

上面的Container组件创建了 function 并将其传递给两个组件。 然后每个组件会在需要时调用 function,例如:

class Wannabe extends React.Component {
  handleClick = () => {
    this.props.doCoolThing();
  };

  render() {
    return (
      <div>
        <h2>Wannabe</h2>

        <button onClick={this.handleClick}>click</button>
      </div>
    );
  }
}

然后在你的应用程序中拥有 function 的组件得到传递的相关道具:

class Cool extends React.Component {
  handleClick = () => {
    this.props.doCoolThing();
  };

  render() {
    return (
      <div>
        <h2>Cool</h2>

        <p>{this.props.counter}</p>

        <button onClick={this.handleClick}>click</button>
      </div>
    );
  }
}

如果您的应用程序正在增长并且您计划对其进行一段时间的开发,您可能需要考虑实施 state 管理解决方案,例如Redux 使state管理更简单。

如果您要使用功能组件而不是 class 组件,则可以使用第三种选择,那就是构建您自己的自定义挂钩。 如果您还不熟悉钩子,那可能有点学习曲线。 您可以阅读React hooks 文档了解如何做到这一点。

我已经创建了一个描述的容器组件和子组件示例的演示。 在此示例中,它们都能够更新Cool组件中显示的 state: https://codesandbox.io/s/dry-hill-r425r?file=/src/App.js


您必须传递来自父级的回调,该回调将在您的第一个 function 执行后调用,更新父级的 state 然后将道具传递给第二个组件以通知它。

import React from "react";

class Component1 extends React.Component {
  componentDidMount() {
    // execute your first function here

    if (this.props.onPushData) {
      this.props.onPushData();
    }
  }

  render() {
    return <p>Component1</p>;
  }
}

class Component2 extends React.Component {
  componentDidUpdate(prevProps) {
    if (prevProps.dataPushed !== this.props.dataPushed) {
      if (this.props.dataPushed) {
        // execute your second function here
      }
    }
  }

  render() {
    return <p>Component2</p>;
  }
}

export default class extends React.Component {
  state = {
    dataPushed: false
  }

  handleDataPush = () => {
    this.setState({ dataPushed: true })
  }

  render() {
    return (
      <div>
        <Component1 onPushData={this.handleDataPush} />
        <Component2 dataPushed={this.state.dataPushed} />
      </div>
    );
  }
}

这是一个 例子

在 component1 中访问 component2 的 function 的一种方法是使用refs

工作演示在这里。

代码片段:

export default class App extends React.Component {
  ref = React.createRef();
  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <Component1 comp2Ref={this.ref} />
        <Component2 ref={this.ref} />
      </div>
    );
  }
}

// Component1.js
export default class Component1 extends React.Component {
  pushData = () => {
    // make the first api call..
    console.log("comp 1 fun");
    // now call component2 function
    console.log(this.props);
    this.props.comp2Ref.current.fetchData();
  };
  render() {
    return (
      <div className="App">
        <h1>component 1</h1>
        <button onClick={this.pushData}>push data button</button>.
      </div>
    );
  }
}

// Component2.js
export default class Component2 extends React.Component {
  fetchData = () => {
    console.log("comp 2 fun");
  };

  render() {
    return (
      <div className="App">
        <h1>component 2</h1>
      </div>
    );
  }
}

处理您的场景的最佳方法是将fetchData function 提升到父级并将其作为 prop 传递给component2

像这样

export default class App extends React.Component {
  state = {
    data: []
  };

  fetchData = () => {
    // fetch the data and update the state(data) and pass it as prosp in component 2
    console.log("comp 2 fun");
  };

  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <Component1 fetchData={this.fetchData} />
        <Component2 data={this.state.data} fetchData={this.fetchData} />
      </div>
    );
  }
}

// Component 1 pushData function

...
 pushData = () => {
    // make the first api call..
    console.log("comp 1 fun");
    // now call component2 function
    console.log(this.props);
    this.props.fetchData();
  };
...


从长远来看,我建议您将Redux添加到当前堆栈,React 在使用大层次结构组件进行扩展以及与后端 API 集成方面存在局限性。

所以如果你正在寻找一个真正的项目在生产中,是时候切换到React-Redux

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM