【问题标题】:Access a React component method / state from outside the component从组件外部访问 React 组件方法/状态
【发布时间】:2018-02-13 15:03:16
【问题描述】:

我通过引用它的 ID 将 reactjs 组件嵌入到现有 HTML 页面中,如 React 教程中所述:

ReactDOM.render(
  <Page />,
  document.getElementById('my-react-compnent')
);

然后:

<div id="my-react-compnent></div>

组件显示并按预期工作。

现在我想将该页面上的一个按钮链接到我的组件(具体来说,我想检索它的状态,但对于这个例子,即使调用它的一个方法也可以)。

换句话说 - 当单击外部按钮时,我想从 Page 组件中调用一个方法?

我该怎么做?

【问题讨论】:

  • 那么当你点击外部按钮时,你想从&lt;Page /&gt;组件中调用一个方法吗?
  • @BrettDeWoody 完全正确。
  • 我会更新问题以更具体地说明这一点。这有点令人困惑。
  • @BrettDeWoody 完成。谢谢。

标签: javascript html reactjs


【解决方案1】:

旧建议

ReactDOM.render 分配返回值确实允许访问组件及其方法。例如,在一个简单的应用程序中,我们可能有:

const PageComponent = ReactDOM.render(<Page />, document.getElementById("app"));

然后我们可以使用PageComponent 访问它,并且可以使用PageComponent.METHOD 访问它的任何方法。

然而,根据文档,这可能会被更改或弃用,因此不推荐使用。

新建议

新的建议是将回调ref 附加到根元素。使用上面相同的示例:

const PageComponent = ReactDOM.render(<Page ref={(pageComponent) => {window.pageComponent = pageComponent}}/>, document.getElementById("app"));

然后我们可以使用window.pageComponent 访问它,并且可以使用window.pageComponent.METHOD 访问它的任何方法。

这也适用于子组件。

这是一个完整的例子:

class ChildComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0
    }
  }

  returnCounter = () => {
    return this.state.counter;
  }
  
  increment = (event) => {
    event.stopPropagation();
    this.setState(prevState => {
      return {
        counter: prevState.counter + 1
      }
    })
  }
  
  render() {
    return (
      <div onClick={this.increment}>
        Child Value - {this.state.counter} - Click to increment
      </div>
    )
  }
}

class Page extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0
    }
  }

  returnCounter = () => {
    return this.state.counter;
  }
  
  increment = () => {
    this.setState(prevState => {
      return {
        counter: prevState.counter + 1
      }
    })
  }

  render() {
    return (
      <div onClick={this.increment}>
        <div>Parent Value - {this.state.counter} - Click to increment</div>
        <ChildComponent ref={(childComponent) => {window.childComponent = childComponent}}/>
      </div>
    )
  }
}

ReactDOM.render(<Page ref={(pageComponent) => {window.pageComponent = pageComponent}} />, document.getElementById("app"));

const parentBtn = document.getElementById("parentButton");
parentBtn.addEventListener("click", event => {
  alert(window.pageComponent.returnCounter());
});

const childBtn = document.getElementById("childButton");
childBtn.addEventListener("click", event => {
  alert(window.childComponent.returnCounter());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>

<button id="parentButton">Get Parent State</button>
<button id="childButton">Get Child State</button>

【讨论】:

  • 谢谢。出于某种原因,PageComponent 对我来说是空的(ReactDOM.render 的返回值。我正在使用material-ui 并且不得不用MuiThemeProvider 包装我的组件(参见material-ui.com/#/customization/themes)。也许它与那个?
  • 是的,MuiThemeProvider 包装器导致了这种行为。我制作了一个“干净”的组件,它的工作原理和你的一样。 :(
  • 有趣。我现在正在尝试访问子组件的方法,这可能会解决您的问题。
  • 不幸的是,分配 ReactDOM.render 的返回值的方法可能会在某些时候被弃用 - reactjs.org/docs/react-dom.html#render
  • 门户网站可能是另一种选择 - reactjs.org/docs/portals.html
猜你喜欢
  • 2016-09-27
  • 2017-12-26
  • 1970-01-01
  • 1970-01-01
  • 2018-09-25
  • 1970-01-01
  • 2014-11-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多