Làm thế nào để truy cập các phương thức thành phần từ trên mạng bên ngoài trong ReactJS?


183

Tại sao tôi không thể truy cập các phương thức thành phần từ bên ngoài trực tuyến trong ReactJS? Tại sao nó không thể và có cách nào để giải quyết nó?

Hãy xem xét mã:

var Parent = React.createClass({
    render: function() {
        var child = <Child />;
        return (
            <div>
                {child.someMethod()} // expect "bar", got a "not a function" error.
            </div>
        );
    }
});

var Child = React.createClass({
    render: function() {
        return (
            <div>
                foo
            </div>
        );
    },
    someMethod: function() {
        return 'bar';
    }
});

React.renderComponent(<Parent />, document.body);

Có lẽ bạn cần Pubsub?
slideshowp2

Câu trả lời:


203

React cung cấp giao diện cho những gì bạn đang cố gắng thực hiện thông qua refthuộc tính . Chỉ định một thành phần a refcurrentthuộc tính của nó sẽ là thành phần tùy chỉnh của bạn:

class Parent extends React.Class {
    constructor(props) {
        this._child = React.createRef();
    }

    componentDidMount() {
        console.log(this._child.current.someMethod()); // Prints 'bar'
    }

    render() {
        return (
            <div>
                <Child ref={this._child} />
            </div>
        );
    }
}

Lưu ý : Điều này sẽ chỉ hoạt động nếu thành phần con được khai báo là một lớp, theo tài liệu được tìm thấy ở đây: https://facebook.github.io/react/docs/refs-and-the-dom.html#adding-a- ref-to-a-class-thành phần

Cập nhật 2019-04-01: Ví dụ đã thay đổi để sử dụng một lớp và createReftheo các tài liệu React mới nhất.

Cập nhật 2016-09-19: Ví dụ đã thay đổi để sử dụng gọi lại ref theo hướng dẫn từ cácref tài liệu thuộc tính String .


Vì vậy, cách duy nhất để giao tiếp giữa hai thành phần con sẽ là cả hai đều có ref và trải qua một phương thức proxy trên cha mẹ chung?
elQueFaltaba

15
React khuyến khích các thành phần điều khiển dữ liệu. Hãy để một đứa trẻ gọi một cuộc gọi lại thay đổi dữ liệu trong tổ tiên của nó và khi dữ liệu đó thay đổi, đứa trẻ khác sẽ nhận được dữ liệu mới propsvà kết xuất lại một cách thích hợp.
Ross Allen

@Ross ALLen, haha ​​vâng, bạn cũng sẽ phải xóa dấu chấm phẩy trong trường hợp đó.
HussienK

@HussienK Tôi thích sử dụng một khối nếu hàm không có giá trị trả về nên ý định rõ ràng đối với nhà phát triển tiếp theo đọc mã. Thay đổi điều đó để {(child) => this._child = child}tạo Hàm luôn trả về true, nhưng giá trị đó không được sử dụng bởi refthuộc tính của React .
Ross Allen

39

Nếu bạn muốn gọi các hàm trên các thành phần từ bên ngoài React, bạn có thể gọi chúng theo giá trị trả về của renderComponent:

var Child = React.createClass({…});
var myChild = React.renderComponent(Child);
myChild.someMethod();

Cách duy nhất để có được một điều khiển đối với thành phần React bên ngoài React là lưu trữ giá trị trả về của React.renderComponent. Nguồn .


1
thực sự nó hoạt động cho phản ứng16. Phương thức kết xuất ReactDOM trả về một tham chiếu đến thành phần (hoặc trả về null cho các thành phần không trạng thái).
Vlad Povalii

37

Ngoài ra, nếu phương thức trên Child thực sự tĩnh (không phải là sản phẩm của các đạo cụ hiện tại, trạng thái), bạn có thể định nghĩa nó staticsvà sau đó truy cập nó như một phương thức lớp tĩnh. Ví dụ:

var Child = React.createClass({
  statics: {
    someMethod: function() {
      return 'bar';
    }
  },
  // ...
});

console.log(Child.someMethod()) // bar

1
Nguồn cho đây là ở đây .
tirdadc

7

Kể từ React 16.3 React.createRefcó thể được sử dụng, (sử dụng ref.currentđể truy cập)

var ref = React.createRef()

var parent = <div><Child ref={ref} /> <button onClick={e=>console.log(ref.current)}</div>

React.renderComponent(parent, document.body)

4

Vì React 0.12 nên API hơi thay đổi . Mã hợp lệ để khởi tạo myChild sẽ như sau:

var Child = React.createClass({…});
var myChild = React.render(React.createElement(Child, {}), mountNode);
myChild.someMethod();

1

Bạn cũng có thể làm như thế này, không chắc đó có phải là một kế hoạch hay không: D

class Parent extends Component {
  handleClick() {
    if (this._getAlert !== null) {
      this._getAlert()
    }
  }

  render() {
    return (
      <div>
        <Child>
        {(getAlert, childScope) => (
          <span> {!this._getAlert ? this._getAlert = getAlert.bind(childScope) : null}</span>
        )}
        </Child>
        <button onClick={() => this.handleClick()}> Click me</button>
      </div>
      );
    }
  }

class Child extends Component {
  constructor() {
    super();
    this.state = { count: 0 }
  }

  getAlert() {
    alert(`Child function called state: ${this.state.count}`);
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return this.props.children(this.getAlert, this)
  }
}

1

Như đã đề cập trong một số ý kiến, ReactDOM.renderkhông còn trả về thể hiện thành phần. Bạn có thể chuyển một refcuộc gọi lại khi kết xuất gốc của thành phần để lấy thể hiện, như vậy:

// React code (jsx)
function MyWidget(el, refCb) {
    ReactDOM.render(<MyComponent ref={refCb} />, el);
}
export default MyWidget;

và:

// vanilla javascript code
var global_widget_instance;

MyApp.MyWidget(document.getElementById('my_container'), function(widget) {
    global_widget_instance = widget;
});

global_widget_instance.myCoolMethod();

-1

Một cách khác rất dễ dàng:

chức năng bên ngoài:

function funx(functionEvents, params) {
  console.log("events of funx function: ", functionEvents);
  console.log("this of component: ", this);
  console.log("params: ", params);
  thisFunction.persist();
}

Trói nó lại:

constructor(props) {
   super(props);
    this.state = {};
    this.funxBinded = funx.bind(this);
  }
}

Vui lòng xem hướng dẫn đầy đủ tại đây: Làm thế nào để sử dụng "cái này" của Thành phần Phản ứng từ bên ngoài?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.