簡體   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