Truyền đạo cụ cho thành phần cha mẹ trong React.js


295

Có cách nào đơn giản để truyền một đứa trẻ propscho cha mẹ của nó bằng các sự kiện, trong React.js không?

var Child = React.createClass({
  render: function() {
    <a onClick={this.props.onClick}>Click me</a>
  }
});

var Parent = React.createClass({
  onClick: function(event) {
    // event.component.props ?why is this not available?
  },
  render: function() {
    <Child onClick={this.onClick} />
  }
});

Tôi biết bạn có thể sử dụng các thành phần được kiểm soát để vượt qua giá trị của đầu vào nhưng sẽ rất tuyệt nếu vượt qua toàn bộ bộ sản phẩm. Đôi khi thành phần con chứa một tập hợp thông tin bạn không cần phải tra cứu.

Có lẽ có một cách để liên kết các thành phần với sự kiện này?

CẬP NHẬT - 9/1/2015

Sau khi sử dụng React được hơn một năm và được thúc đẩy bởi câu trả lời của Sebastien Lorber, tôi đã kết luận việc chuyển các thành phần con thành các đối số cho các hàm trong cha mẹ thực tế không phải là cách React, cũng không phải là một ý tưởng hay. Tôi đã chuyển câu trả lời.


Có nhiều câu trả lời cho các vấn đề tương tự ( ở đâyở đây ), nhưng không có câu trả lời nào có vẻ đặc biệt thanh lịch
Bojangles

Tôi đồng ý - truyền các sự kiện lên chuỗi là tuyệt vời, nhưng thật tuyệt vời khi biết chắc chắn thành phần nào khởi nguồn sự kiện.
KendallB

Xin hãy xem câu trả lời của tôi, vì tôi nghĩ rằng câu trả lời được chấp nhận là không đủ tốt; stackoverflow.com/a/31756470/82609
Sebastien Lorber

1
kit n 'kaboodle - Để có được mọi thứ bao gồm. Để có được tất cả các chuông và còi. Sự kết hợp. urbandipedia.com/define.php?term=kit%20and%20caboodle
Filip Bartuzi

Câu trả lời:


268

Chỉnh sửa : xem các ví dụ kết thúc cho các ví dụ cập nhật ES6.

Câu trả lời này chỉ đơn giản là xử lý các trường hợp quan hệ cha mẹ trực tiếp. Khi cha mẹ và con cái có khả năng có nhiều trung gian, hãy kiểm tra câu trả lời này .

Các giải pháp khác đang thiếu điểm

Trong khi chúng vẫn hoạt động tốt, các câu trả lời khác đang thiếu một cái gì đó rất quan trọng.

Có cách nào đơn giản để truyền đạo cụ của một đứa trẻ cho cha mẹ của nó bằng các sự kiện, trong React.js không?

Cha mẹ đã có chỗ dựa cho con! : nếu đứa trẻ có chỗ dựa, thì đó là vì cha mẹ của nó đã cung cấp chỗ dựa đó cho đứa trẻ! Tại sao bạn muốn đứa trẻ trả lại chỗ dựa cho cha mẹ, trong khi cha mẹ rõ ràng đã có chỗ dựa đó?

Thực hiện tốt hơn

Đứa trẻ : nó thực sự không phải phức tạp hơn thế.

var Child = React.createClass({
  render: function () {
    return <button onClick={this.props.onClick}>{this.props.text}</button>;
  },
});

Cha mẹ có con độc thân : sử dụng giá trị nó truyền cho con

var Parent = React.createClass({
  getInitialState: function() {
     return {childText: "Click me! (parent prop)"};
  },
  render: function () {
    return (
      <Child onClick={this.handleChildClick} text={this.state.childText}/>
    );
  },
  handleChildClick: function(event) {
     // You can access the prop you pass to the children 
     // because you already have it! 
     // Here you have it in state but it could also be
     //  in props, coming from another parent.
     alert("The Child button text is: " + this.state.childText);
     // You can also access the target of the click here 
     // if you want to do some magic stuff
     alert("The Child HTML is: " + event.target.outerHTML);
  }
});

JsFiddle

Cha mẹ có danh sách con cái : bạn vẫn có mọi thứ bạn cần cho cha mẹ và không cần làm cho con trở nên phức tạp hơn.

var Parent = React.createClass({
  getInitialState: function() {
     return {childrenData: [
         {childText: "Click me 1!", childNumber: 1},
         {childText: "Click me 2!", childNumber: 2}
     ]};
  },
  render: function () {
    var children = this.state.childrenData.map(function(childData,childIndex) {
        return <Child onClick={this.handleChildClick.bind(null,childData)} text={childData.childText}/>;
    }.bind(this));
    return <div>{children}</div>;
  },

  handleChildClick: function(childData,event) {
     alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
     alert("The Child HTML is: " + event.target.outerHTML);
  }
});

JsFiddle

Cũng có thể sử dụng this.handleChildClick.bind(null,childIndex)và sau đó sử dụngthis.state.childrenData[childIndex]

Lưu ý rằng chúng tôi đang ràng buộc với một nullbối cảnh vì nếu không React sẽ đưa ra cảnh báo liên quan đến hệ thống tự động gắn kết của nó . Sử dụng null có nghĩa là bạn không muốn thay đổi bối cảnh chức năng. Xem thêm .

Về đóng gói và khớp nối trong các câu trả lời khác

Đây là một ý tưởng tồi đối với việc ghép và đóng gói:

var Parent = React.createClass({
  handleClick: function(childComponent) {
     // using childComponent.props
     // using childComponent.refs.button
     // or anything else using childComponent
  },
  render: function() {
    <Child onClick={this.handleClick} />
  }
});

Sử dụng đạo cụ : Như tôi đã giải thích ở trên, bạn đã có đạo cụ trong cha mẹ nên việc truyền toàn bộ thành phần con để truy cập đạo cụ là vô ích.

Sử dụng refs : Bạn đã có mục tiêu nhấp chuột trong sự kiện và trong hầu hết các trường hợp, điều này là đủ. Ngoài ra, bạn có thể đã sử dụng một ref trực tiếp cho trẻ:

<Child ref="theChild" .../>

Và truy cập nút DOM trong cha mẹ với

React.findDOMNode(this.refs.theChild)

Đối với các trường hợp nâng cao hơn mà bạn muốn truy cập nhiều ref của đứa trẻ trong cha mẹ, đứa trẻ có thể chuyển tất cả các nút dom trực tiếp trong cuộc gọi lại.

Thành phần này có một giao diện (đạo cụ) và cha mẹ không nên thừa nhận bất cứ điều gì về hoạt động bên trong của đứa trẻ, bao gồm cả cấu trúc DOM bên trong của nó hoặc các nút DOM mà nó tuyên bố giới thiệu. Một phụ huynh sử dụng ref của một đứa trẻ có nghĩa là bạn kết hợp chặt chẽ 2 thành phần.

Để minh họa vấn đề, tôi sẽ lấy trích dẫn này về Shadow DOM , được sử dụng bên trong các trình duyệt để hiển thị những thứ như thanh trượt, thanh cuộn, trình phát video ...:

Họ đã tạo ra một ranh giới giữa những gì bạn, nhà phát triển Web có thể tiếp cận và những gì được coi là chi tiết triển khai, do đó không thể tiếp cận được với bạn. Tuy nhiên, trình duyệt có thể vượt qua ranh giới này tùy ý. Với ranh giới này, họ có thể xây dựng tất cả các yếu tố HTML bằng cách sử dụng cùng các công nghệ Web cũ, ngoài các div và spans giống như bạn.

Vấn đề là nếu bạn để trẻ thực hiện các chi tiết rò rỉ vào cha mẹ, bạn sẽ rất khó để cấu trúc lại trẻ mà không ảnh hưởng đến cha mẹ. Điều này có nghĩa là với tư cách là một tác giả thư viện (hoặc là một trình soạn thảo trình duyệt với Shadow DOM), điều này rất nguy hiểm vì bạn cho phép máy khách truy cập quá nhiều, khiến cho việc nâng cấp mã rất khó mà không phá vỡ tính tương thích.

Nếu Chrome đã triển khai thanh cuộn của mình cho phép khách hàng truy cập vào các nút dom bên trong của thanh cuộn đó, điều này có nghĩa là khách hàng có thể có khả năng phá vỡ thanh cuộn đó và các ứng dụng sẽ dễ dàng phá vỡ hơn khi Chrome thực hiện cập nhật tự động sau khi tái cấu trúc thanh cuộn ... Thay vào đó, họ chỉ cấp quyền truy cập vào một số thứ an toàn như tùy chỉnh một số phần của thanh cuộn bằng CSS.

Về việc sử dụng bất cứ điều gì khác

Truyền toàn bộ thành phần trong cuộc gọi lại rất nguy hiểm và có thể khiến các nhà phát triển mới làm những việc rất kỳ lạ như gọi childComponent.setState(...)hoặc childComponent.forceUpdate()hoặc gán cho nó các biến mới, bên trong cha mẹ, khiến cho toàn bộ ứng dụng trở nên khó khăn hơn nhiều.


Chỉnh sửa: ví dụ ES6

Như nhiều người hiện đang sử dụng ES6, đây là những ví dụ tương tự cho cú pháp ES6

Đứa trẻ có thể rất đơn giản:

const Child = ({
  onClick, 
  text
}) => (
  <button onClick={onClick}>
    {text}
  </button>
)

Phụ huynh có thể là một lớp (và cuối cùng nó có thể tự quản lý trạng thái, nhưng tôi chuyển nó làm đạo cụ ở đây:

class Parent1 extends React.Component {
  handleChildClick(childData,event) {
     alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
     alert("The Child HTML is: " + event.target.outerHTML);
  }
  render() {
    return (
      <div>
        {this.props.childrenData.map(child => (
          <Child
            key={child.childNumber}
            text={child.childText} 
            onClick={e => this.handleChildClick(child,e)}
          />
        ))}
      </div>
    );
  }
}

Nhưng nó cũng có thể được đơn giản hóa nếu không cần quản lý trạng thái:

const Parent2 = ({childrenData}) => (
  <div>
     {childrenData.map(child => (
       <Child
         key={child.childNumber}
         text={child.childText} 
         onClick={e => {
            alert("The Child button data is: " + child.childText + " - " + child.childNumber);
                    alert("The Child HTML is: " + e.target.outerHTML);
         }}
       />
     ))}
  </div>
)

JsFiddle


CẢNH BÁO PERF (áp dụng cho ES5 / ES6): nếu bạn đang sử dụng PureComponenthoặc shouldComponentUpdate, các triển khai trên sẽ không được tối ưu hóa theo mặc định vì sử dụng onClick={e => doSomething()}hoặc liên kết trực tiếp trong giai đoạn kết xuất, bởi vì nó sẽ tạo ra một chức năng mới mỗi khi cha mẹ kết xuất. Nếu đây là một nút cổ chai hoàn hảo trong ứng dụng của bạn, bạn có thể truyền dữ liệu cho trẻ em và từ chối nó trong cuộc gọi lại "ổn định" (được đặt trên lớp cha và liên kết với thistrình xây dựng lớp) để PureComponenttối ưu hóa có thể khởi động hoặc bạn có thể tự thực hiện shouldComponentUpdatevà bỏ qua cuộc gọi lại trong kiểm tra so sánh đạo cụ.

Bạn cũng có thể sử dụng thư viện Recompose , cung cấp các thành phần bậc cao hơn để đạt được tối ưu hóa tinh chỉnh:

// A component that is expensive to render
const ExpensiveComponent = ({ propA, propB }) => {...}

// Optimized version of same component, using shallow comparison of props
// Same effect as React's PureRenderMixin
const OptimizedComponent = pure(ExpensiveComponent)

// Even more optimized: only updates if specific prop keys have changed
const HyperOptimizedComponent = onlyUpdateForKeys(['propA', 'propB'])(ExpensiveComponent)

Trong trường hợp này, bạn có thể tối ưu hóa thành phần Con bằng cách sử dụng:

const OptimizedChild = onlyUpdateForKeys(['text'])(Child)

1
Vâng, tôi đã dành năm ngoái sử dụng React, tôi đồng ý - không có lý do chính đáng nào để chuyển các thành phần khởi tạo xung quanh thông qua các chức năng. Tôi sẽ phản đối câu trả lời của riêng tôi. Tôi cũng sẵn sàng chuyển câu trả lời, có lẽ với một số sửa đổi: "Thực hiện tốt hơn" của bạn không giải quyết được lý do thực sự của câu hỏi này, đó là "Làm thế nào để tôi biết con nào được chọn trong một nhóm?" Flux là câu trả lời cho bất kỳ ứng dụng có kích thước phù hợp nào, tuy nhiên, trong các ứng dụng nhỏ, tôi rất vui khi truyền các giá trị (không phải thành phần) sao lưu chuỗi cuộc gọi thông qua chức năng trên props. Đồng ý?
KendallB

@KendallB rất vui khi bạn đồng ý với câu trả lời của tôi :) How do I know which of my children was chosen among a group?đây không thực sự là một phần của câu hỏi ban đầu, nhưng tôi đã bao gồm giải pháp trong câu trả lời của mình. Không giống như chỉnh sửa của bạn, tôi nghĩ rằng không cần thiết phải sửa đổi đứa trẻ, ngay cả khi xử lý một danh sách, vì bạn có thể sử dụng bindtrực tiếp trong cha mẹ.
Sebastien Lorber

Tôi đã thực hiện một chỉnh sửa cho câu trả lời của bạn, phần về refs. omerwazir.com/posts/react-getdomnode-replaces-with-findDOMNode
ffxsam

Xin chào @SebastienLorber Tôi đến từ tương lai. Về dòng này onClick={this.handleChildClick.bind(null,childData)}bạn đã đề cập về autobinding Có phải bây giờ nó vẫn được áp dụng khi React chưa được đưa vào mô hình lớp . Tôi đã đọc rất nhiều thứ nhưng phần này vẫn làm tôi bối rối. Tôi đang sử dụng ES6 class modelbằng cách này, vì vậy tôi đã thay đổi nullđến thisvà mã của tôi dường như vẫn làm việc. Làm thế nào bạn có thể dịch phần mã đó thành kiểu ES6?
JohnnyQ 8/11/2016

Tôi cũng đang vật lộn để làm việc này trong React mới nhất, cần phải thay đổi điều gì?
Hussein Duvigneau

143

Cập nhật (9/1/15): OP đã đưa ra câu hỏi này một chút về mục tiêu di động. Nó đã được cập nhật lại. Vì vậy, tôi cảm thấy có trách nhiệm để cập nhật trả lời của tôi.

Đầu tiên, một câu trả lời cho ví dụ được cung cấp của bạn:

Vâng, điều này là có thể.

Bạn có thể giải quyết điều này bằng cách cập nhật Child's onClickthành this.props.onClick.bind(null, this):

var Child = React.createClass({
  render: function () {
    return <a onClick={this.props.onClick.bind(null, this)}>Click me</a>;
  }
});

Trình xử lý sự kiện trong Parent của bạn sau đó có thể truy cập vào thành phần và sự kiện như vậy:

  onClick: function (component, event) {
    // console.log(component, event);
  },

Ảnh chụp nhanh của JSBin


Nhưng bản thân câu hỏi đã gây hiểu nhầm

Cha mẹ đã biết Con props.

Điều này không rõ ràng trong ví dụ được cung cấp bởi vì không có đạo cụ nào thực sự được cung cấp. Mã mẫu này có thể hỗ trợ tốt hơn cho câu hỏi đang được hỏi:

var Child = React.createClass({
  render: function () {
    return <a onClick={this.props.onClick}> {this.props.text} </a>;
  }
});

var Parent = React.createClass({
  getInitialState: function () {
    return { text: "Click here" };
  },
  onClick: function (event) {
    // event.component.props ?why is this not available? 
  },
  render: function() {
    return <Child onClick={this.onClick} text={this.state.text} />;
  }
});

Nó trở nên rõ ràng hơn trong ví dụ này rằng bạn đã biết đạo cụ của Child là gì.

Ảnh chụp nhanh của JSBin


Nếu nó thực sự về việc sử dụng đạo cụ của một đứa trẻ

Nếu đó thực sự là về việc sử dụng đạo cụ của Trẻ em, bạn có thể tránh mọi sự móc nối với Trẻ hoàn toàn.

JSX có API thuộc tính lây lan mà tôi thường sử dụng trên các thành phần như Child. Nó nhận tất cả propsvà áp dụng chúng cho một thành phần. Đứa trẻ sẽ trông như thế này:

var Child = React.createClass({
  render: function () {
    return <a {...this.props}> {this.props.text} </a>;
  }
});

Cho phép bạn sử dụng các giá trị trực tiếp trong Phụ huynh:

var Parent = React.createClass({
  getInitialState: function () {
    return { text: "Click here" };
  },
  onClick: function (text) {
    alert(text);
  },
  render: function() {
    return <Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />;
  }
});

Ảnh chụp nhanh của JSBin


Và không có cấu hình bổ sung cần thiết khi bạn kết nối các thành phần con bổ sung

var Parent = React.createClass({
  getInitialState: function () {
    return {
      text: "Click here",
      text2: "No, Click here",
    };
  },
  onClick: function (text) {
    alert(text);
  },
  render: function() {
    return <div>
      <Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />
      <Child onClick={this.onClick.bind(null, this.state.text2)} text={this.state.text2} />
    </div>;
  }
});

Ảnh chụp nhanh của JSBin

Nhưng tôi nghi ngờ đó không phải là trường hợp sử dụng thực tế của bạn. Vì vậy, hãy đào sâu hơn nữa


Một ví dụ thực tế mạnh mẽ

Bản chất chung của ví dụ được cung cấp là một điều khó nói. Tôi đã tạo ra một thành phần thể hiện việc sử dụng thực tế cho câu hỏi ở trên, được triển khai theo cách rất Phản ứng :

Ví dụ làm việc
DTServiceCalculator repo DTServiceCalculator

Thành phần này là một máy tính dịch vụ đơn giản. Bạn cung cấp cho nó một danh sách các dịch vụ (có tên và giá) và nó sẽ tính tổng giá đã chọn.

Trẻ em vô phúc vô minh.

ServiceItemlà thành phần con trong ví dụ này. Nó không có nhiều ý kiến ​​về thế giới bên ngoài. Nó đòi hỏi một vài đạo cụ , một trong số đó là một chức năng được gọi khi nhấp vào.

<div onClick={this.props.handleClick.bind(this.props.index)} />

Không có gì ngoài việc gọi lại cuộc gọi được cung cấp handleClickvới index[ nguồn ] được cung cấp .

Cha mẹ là trẻ em

DTServicesCalculatorlà thành phần cha mẹ là ví dụ này. Đó cũng là một đứa trẻ. Hãy nhìn xem.

DTServiceCalculatortạo một danh sách các thành phần con ServiceItemvà cung cấp cho chúng các đạo cụ [ nguồn ]. Nó là thành phần cha mẹ của ServiceItemnhưng nó là thành phần con của thành phần vượt qua nó trong danh sách. Nó không sở hữu dữ liệu. Vì vậy, nó một lần nữa ủy quyền xử lý thành phần cho nguồn thành phần mẹ của nó

<ServiceItem chosen={chosen} index={i} key={id} price={price} name={name} onSelect={this.props.handleServiceItem} />

handleServiceItemnắm bắt chỉ mục, được truyền từ đứa trẻ và cung cấp cho cha mẹ [ nguồn ]

handleServiceClick (index) {
  this.props.onSelect(index);
}

Chủ sở hữu biết tất cả mọi thứ

Khái niệm về quyền sở hữu của người nổi tiếng là một điều quan trọng trong React. Tôi khuyên bạn nên đọc thêm về nó ở đây .

Trong ví dụ tôi đã trình bày, tôi tiếp tục ủy thác xử lý một sự kiện lên cây thành phần cho đến khi chúng ta đến thành phần sở hữu trạng thái.

Cuối cùng khi chúng tôi đến đó, chúng tôi xử lý lựa chọn / bỏ trạng thái như vậy [ nguồn ]:

handleSelect (index) {
  let services = […this.state.services];
  services[index].chosen = (services[index].chosen) ? false : true;
  this.setState({ services: services });
}


Phần kết luận

Cố gắng giữ cho các thành phần bên ngoài của bạn càng mờ càng tốt. Cố gắng đảm bảo rằng họ có rất ít sở thích về cách một thành phần cha mẹ có thể chọn thực hiện chúng.

Giữ cho biết ai sở hữu dữ liệu bạn đang thao túng. Trong hầu hết các trường hợp, bạn sẽ cần ủy thác sự kiện xử lý cây cho thành phần sở hữu trạng thái đó.

Ngoài ra: Mẫu Flux là một cách tốt để giảm loại hookup cần thiết này trong các ứng dụng.


Cảm ơn câu trả lời súc tích, nó thực sự giúp tôi hiểu React hơn một chút! Tôi có một câu hỏi dọc theo cùng một dòng. Tôi đang sử dụng Flux cho pub / sub. Thay vì chuyển trình xử lý sự kiện Con cho Phụ huynh như ví dụ của bạn, có thể thực hiện điều này như một 'hành động' và lắng nghe nó. Bạn sẽ xem đây là một sự thay thế tốt và sử dụng Flux?
Pathsofdesign

1
Cảm ơn @Pathsofdesign! Nó sẽ phụ thuộc. Flux có khái niệm về Trình điều khiển-Lượt xem. Trong ví dụ này, Parentcó thể là Chế độ xem điều khiển, trong khi Childchỉ là Chế độ xem câm (thành phần). Chỉ điều khiển-Lượt xem mới có kiến ​​thức về ứng dụng. Trong trường hợp này, bạn vẫn sẽ chuyển Hành động từ Parentsang Childlàm chỗ dựa. Vì bản thân Hành động có liên quan, Flux có một mẫu được quy định mạnh mẽ để tương tác giữa các Hành động để cập nhật Chế độ xem. facebook.github.io/flux/docs/ cường
chantastic

1
onClick={this.onClick.bind(null, this.state.text)}không cần phải ràng buộc nhà nước như cha mẹ có điều đó. vì vậy chỉ cần onClick={this.onClick}làm việc ở đâu onClick = ()=>{const text = this.state.text;..}trong cha mẹ
Shishir Arora

25

Có vẻ như có một câu trả lời đơn giản. Xem xét điều này:

var Child = React.createClass({
  render: function() {
    <a onClick={this.props.onClick.bind(null, this)}>Click me</a>
  }
});

var Parent = React.createClass({
  onClick: function(component, event) {
    component.props // #=> {Object...}
  },
  render: function() {
    <Child onClick={this.onClick} />
  }
});

Điều quan trọng là kêu gọi bind(null, this)trên this.props.onClicksự kiện, truyền từ cha mẹ. Bây giờ, hàm onClick chấp nhận đối số component, VÀ event. Tôi nghĩ đó là điều tốt nhất trong tất cả các thế giới.

CẬP NHẬT: 9/1/2015

Đây là một ý tưởng tồi: để cho các chi tiết thực hiện của trẻ bị rò rỉ cho cha mẹ không bao giờ là một con đường tốt. Xem câu trả lời của Sebastien Lorber.


arent các đối số sai cách (nơi đổi chỗ)?
Surrican

1
@TheSurrican Không, nó hoàn toàn ổn. Đối số đầu tiên được ràng buộc thistrong hàm (dù sao không cần thiết) và đối số thứ hai được thêm vào làm đối số đầu tiên khi onClick được gọi.
manody

13

Câu hỏi là làm thế nào để truyền đối số từ con sang thành phần cha. Ví dụ này dễ sử dụng và thử nghiệm:

//Child component
class Child extends React.Component {
    render() {
        var handleToUpdate  =   this.props.handleToUpdate;
        return (<div><button onClick={() => handleToUpdate('someVar')}>Push me</button></div>
        )
    }
}

//Parent component
class Parent extends React.Component {
    constructor(props) {
        super(props);
        var handleToUpdate  = this.handleToUpdate.bind(this);
    }

    handleToUpdate(someArg){
        alert('We pass argument from Child to Parent: \n' + someArg);
    }

    render() {
        var handleToUpdate  =   this.handleToUpdate;
        return (<div>
          <Child handleToUpdate = {handleToUpdate.bind(this)} />
        </div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <Parent />,
        document.querySelector("#demo")
    );
}

Nhìn vào JSFIDDLE


Trong trường hợp của tôi, nó quên chuyển chức năng gọi lại vào click ()
Long Nguyễn

6

Về cơ bản, bạn sử dụng đạo cụ để gửi thông tin đến và từ Trẻ em và Phụ huynh.

Thêm vào tất cả các câu trả lời tuyệt vời, tôi xin đưa ra một ví dụ đơn giản giải thích việc chuyển các giá trị từ thành phần con sang thành phần cha mẹ trong React

App.js

class App extends React.Component {
      constructor(){
            super();
            this.handleFilterUpdate = this.handleFilterUpdate.bind(this);
            this.state={name:'igi'}
      }
      handleFilterUpdate(filterValue) {
            this.setState({
                  name: filterValue
            });
      }
   render() {
      return (
        <div>
            <Header change={this.handleFilterUpdate} name={this.state.name} />
            <p>{this.state.name}</p>
        </div>
      );
   }
}

Header.js

class Header extends React.Component {
      constructor(){
            super();
            this.state={
                  names: 'jessy'
            }
      }
      Change(event) {

      // this.props.change(this.state.names);
      this.props.change('jessy');
  }

   render() {
      return (
       <button onClick={this.Change.bind(this)}>click</button>

      );
   }
}

Main.js

import React from 'react';
import ReactDOM from 'react-dom';

import App from './App.jsx';

ReactDOM.render(<App />, document.getElementById('app'));

Đó là, bây giờ bạn có thể chuyển các giá trị từ máy khách của bạn đến máy chủ.

Hãy xem chức năng Thay đổi trong Header.js

Change(event) {
      // this.props.change(this.state.names);
      this.props.change('jessy');
  }

Đây là cách bạn đẩy các giá trị vào các đạo cụ từ máy khách đến máy chủ


Tôi có thể biết Đây là cách bạn đẩy các giá trị vào các đạo cụ từ máy khách đến máy chủ, ý của bạn là gì bởi tuyên bố này
G1P

2

Dưới đây là cách thực hiện ES6 3 bước đơn giản bằng cách sử dụng liên kết hàm trong hàm tạo cha. Đây là cách đầu tiên mà hướng dẫn phản ứng chính thức khuyến nghị (cũng có cú pháp trường công khai không được đề cập ở đây). Bạn có thể tìm thấy tất cả các thông tin này ở đây https://reactjs.org/docs/handling-events.html

Ràng buộc các chức năng của cha mẹ để trẻ em có thể gọi chúng (Và truyền dữ liệu cho phụ huynh !: D)

  1. Đảm bảo trong hàm tạo cha mẹ, bạn liên kết hàm bạn đã tạo trong cha mẹ
  2. Truyền hàm bị ràng buộc xuống cho trẻ dưới dạng chống đỡ (Không có lambda vì chúng tôi đang chuyển một ref cho hàm)
  3. Gọi hàm bị ràng buộc từ một sự kiện con (Lambda! Chúng tôi đang gọi hàm khi sự kiện được kích hoạt. Nếu chúng ta không làm điều này, chức năng sẽ tự động chạy khi tải và không được kích hoạt trong sự kiện.)

Chức năng phụ huynh

handleFilterApply(filterVals){} 

Phụ huynh xây dựng

this.handleFilterApply = this.handleFilterApply.bind(this);

Prop truyền cho trẻ em

onApplyClick = {this.handleFilterApply}

Cuộc gọi sự kiện trẻ em

onClick = {() => {props.onApplyClick(filterVals)}

0

Đây là một ví dụ mà không sử dụng sự kiện onClick. Tôi chỉ đơn giản là truyền một chức năng gọi lại cho trẻ bằng đạo cụ. Với cuộc gọi lại đó, cuộc gọi con cũng gửi dữ liệu trở lại. Tôi đã được truyền cảm hứng bởi các ví dụ trong các tài liệu .

Ví dụ nhỏ (đây là trong một tệp tsx, vì vậy đạo cụ và trạng thái phải được khai báo đầy đủ, tôi đã xóa một số logic ra khỏi các thành phần, vì vậy nó ít mã hơn).

* Cập nhật: Quan trọng là liên kết điều này với cuộc gọi lại, nếu không thì cuộc gọi lại có phạm vi của con chứ không phải cha mẹ. Vấn đề duy nhất: đó là cha mẹ "cũ" ...

Triệu chứng là cha mẹ:

interface SymptomChooserState {
  // true when a symptom was pressed can now add more detail
  isInDetailMode: boolean
  // since when user has this symptoms
  sinceDate: Date,
}

class SymptomChooser extends Component<{}, SymptomChooserState> {

  state = {
    isInDetailMode: false,
    sinceDate: new Date()
  }

  helloParent(symptom: Symptom) {
    console.log("This is parent of: ", symptom.props.name);
    // TODO enable detail mode
  }

  render() {
    return (
      <View>
        <Symptom name='Fieber' callback={this.helloParent.bind(this)} />
      </View>
    );
  }
}

Triệu chứng là đứa trẻ (trong đạo cụ của đứa trẻ tôi đã khai báo hàm gọi lại, trong chức năng được chọnSymptom, cuộc gọi lại được gọi):

interface SymptomProps {
  // name of the symptom
  name: string,
  // callback to notify SymptomChooser about selected Symptom.
  callback: (symptom: Symptom) => void
}

class Symptom extends Component<SymptomProps, SymptomState>{

  state = {
    isSelected: false,
    severity: 0
  }

  selectedSymptom() {
    this.setState({ isSelected: true });
    this.props.callback(this);
  }

  render() {
    return (
      // symptom is not selected
      <Button
        style={[AppStyle.button]}
        onPress={this.selectedSymptom.bind(this)}>
        <Text style={[AppStyle.textButton]}>{this.props.name}</Text>
      </Button>
    );
  }
}
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.