Làm thế nào để chuyển một thành phần phản ứng vào thành phần phản ứng khác để vượt qua nội dung của thành phần đầu tiên?


215

Có cách nào để chuyển một thành phần này sang thành phần phản ứng khác không? Tôi muốn tạo ra một thành phần phản ứng mô hình và chuyển vào một thành phần phản ứng khác để vượt qua nội dung đó.

Chỉnh sửa: Đây là một codepen ReacJS minh họa những gì tôi đang cố gắng làm. http://codepen.io/aallbrig/pen/bEhjo

HTML

<div id="my-component">
    <p>Hi!</p>
</div>

Phản ứng

/**@jsx React.DOM*/

var BasicTransclusion = React.createClass({
  render: function() {
    // Below 'Added title' should be the child content of <p>Hi!</p>
    return (
      <div>
        <p> Added title </p>
        {this.props.children}
      </div>
    )
  }
});

React.renderComponent(BasicTransclusion(), document.getElementById('my-component'));

Câu trả lời:


197

Bạn có thể sử dụng this.props.childrenđể kết xuất bất cứ thứ gì con chứa thành phần:

const Wrap = ({ children }) => <div>{children}</div>

export default () => <Wrap><h1>Hello word</h1></Wrap>

4
Tôi sẽ sử dụng câu trả lời này. this.props.childrenlà một phần của API thành phần và dự kiến ​​sẽ được sử dụng theo cách này. Các ví dụ của nhóm React sử dụng kỹ thuật này, như trong việc chuyển đạo cụ và khi nói về một đứa trẻ .
Ross Allen

Từ nhận xét của tôi dưới đây: Bằng cách chuyển nó dưới dạng prop, bạn thậm chí có thể đặt tên cho nó và sử dụng propTypes để gõ kiểm tra.
returneax

1
@Andrew ALLbright: Ví dụ của bạn không vượt qua bất kỳ đứa trẻ nào. Công việc này: codepen.io/ssorallen/pen/Dyjmk
Ross Allen

Và trong trường hợp sau đó bạn muốn nhận được các Nút DOM của trẻ em: stackoverflow.com/questions/29568721/
mẹo

124

Lưu ý tôi đã cung cấp một câu trả lời sâu hơn ở đây

Trình bao bọc thời gian chạy:

Đó là cách thành ngữ nhất.

const Wrapper = ({children}) => (
  <div>
    <div>header</div>
    <div>{children}</div>
    <div>footer</div>
  </div>
);

const App = () => <div>Hello</div>;

const WrappedApp = () => (
  <Wrapper>
    <App/>
  </Wrapper>
);

Lưu ý rằng đó childrenlà "chỗ dựa đặc biệt" trong React và ví dụ trên là đường cú pháp và (gần như) tương đương với<Wrapper children={<App/>}/>


Trình bao bọc khởi tạo / HOC

Bạn có thể sử dụng Thành phần bậc cao (HOC). Họ đã được thêm vào tài liệu chính thức gần đây.

// Signature may look fancy but it's just 
// a function that takes a component and returns a new component
const wrapHOC = (WrappedComponent) => (props) => (
  <div>
    <div>header</div>
    <div><WrappedComponent {...props}/></div>
    <div>footer</div>
  </div>
)

const App = () => <div>Hello</div>;

const WrappedApp = wrapHOC(App);

Điều này có thể dẫn đến (ít) hiệu suất tốt hơn vì thành phần trình bao bọc có thể làm ngắn mạch kết xuất trước một bước với ShouldComponentUpdate, trong khi trong trường hợp trình bao bọc thời gian chạy, prop trẻ em có thể luôn luôn là một ReactEuity khác và gây ra kết xuất lại ngay cả khi các thành phần của bạn mở rộng PureComponent.

Lưu ý rằng connectRedux từng là trình bao bọc thời gian chạy nhưng đã được thay đổi thành HOC vì nó cho phép tránh kết xuất lại vô dụng nếu bạn sử dụng puretùy chọn (theo mặc định là đúng)

Bạn không bao giờ nên gọi HOC trong giai đoạn kết xuất vì việc tạo các thành phần React có thể tốn kém. Bạn nên gọi các hàm bao này lúc khởi tạo.


Lưu ý rằng khi sử dụng các thành phần chức năng như trên, phiên bản HOC không cung cấp bất kỳ tối ưu hóa hữu ích nào vì các thành phần chức năng không trạng thái không thực hiện shouldComponentUpdate

Giải thích thêm tại đây: https://stackoverflow.com/a/31564812/82609


29
const ParentComponent = (props) => {
  return(
    {props.childComponent}
    //...additional JSX...
  )
}

//import component
import MyComponent from //...where ever

//place in var
const myComponent = <MyComponent />

//pass as prop
<ParentComponent childComponent={myComponent} />

Điều này sẽ đúng nếu nó ... Phản ứng 15.x không cho phép bạn trả về một thành phần đa nút. React 16 (hay còn gọi là React Fiber) sẽ cho phép nhiều nút. Đây là bản sửa lỗi cho mẫu mã của bạn: const ParentComponent = (props) => ({props.childComponent}); nhập khẩu myComponent từ //...where bao giờ const myComponent = <myComponent /> // vượt qua như prop <ParentComponent childComponent = {myComponent} />
Andrew Allbright

13

Facebook khuyến nghị sử dụng thành phần không trạng thái Nguồn: https://facebook.github.io/react/docs/reUs-components.html

Trong một thế giới lý tưởng, hầu hết các thành phần của bạn sẽ là các hàm không trạng thái bởi vì trong tương lai chúng ta cũng sẽ có thể tối ưu hóa hiệu suất cụ thể cho các thành phần này bằng cách tránh các kiểm tra và phân bổ bộ nhớ không cần thiết. Đây là mô hình được đề nghị, khi có thể.

function Label(props){
    return <span>{props.label}</span>;
}

function Hello(props){
    return <div>{props.label}{props.name}</div>;
}

var hello = Hello({name:"Joe", label:Label({label:"I am "})});

ReactDOM.render(hello,mountNode);

13

Bạn có thể vượt qua nó như một chỗ dựa bình thường: foo={<ComponentOne />}

Ví dụ:

const ComponentOne = () => <div>Hello world!</div>
const ComponentTwo = () => (
  <div>
    <div>Hola el mundo!</div>
    <ComponentThree foo={<ComponentOne />} />
  </div>
)
const ComponentThree = ({ foo }) => <div>{foo}</div>

9

tôi thích sử dụng API tích hợp React:

import React, {cloneElement, Component} from "react";
import PropTypes from "prop-types";

export class Test extends Component {
  render() {
    const {children, wrapper} = this.props;
    return (
      cloneElement(wrapper, {
        ...wrapper.props,
        children
      })
    );
  }
}

Test.propTypes = {
  wrapper: PropTypes.element,
  // ... other props
};

Test.defaultProps = {
  wrapper: <div/>,
  // ... other props
};

sau đó bạn có thể thay thế div trình bao bọc bằng những gì bạn muốn:

<Test wrapper={<span className="LOL"/>}>
  <div>child1</div>
  <div>child2</div>
</Test> 

5

Bạn có thể vượt qua trong một thành phần thông qua. các đạo cụ và kết xuất nó với phép nội suy.

var DivWrapper = React.createClass({
    render: function() {
        return <div>{ this.props.child }</div>;
    }
});

Sau đó, bạn sẽ chuyển qua một cuộc propgọi child, đó sẽ là một thành phần React.


1
Điều này sẽ dẫn đến việc chuyển các thành phần thông qua các thuộc tính chứ không phải là trẻ em. Nếu bạn sử dụng this.props.childrennhư được đề xuất trong một câu trả lời khác, bạn có thể viết trẻ em như trẻ em thay vì attrs.
Ross Allen

1
@ssorallen bạn đã không nói lý do tại sao một người tốt hơn bằng mọi cách ... Bằng cách chuyển nó dưới dạng chống đỡ, bạn thậm chí có thể đặt tên cho nó và sử dụng propTypes để gõ kiểm tra.
returneax

1
Mọi phần tử bạn sử dụng trong JSX chỉ là một thành phần. Nếu họ sử dụng phương pháp này, bạn sẽ không thể viết ngay cả ví dụ ngắn của mình. Nó sẽ trở thành <div child={this.props.child />.
Ross Allen

1
Kiểm tra phiên bản JavaScript (những gì JSX biến nó thành): jsfiddle.net/ssorallen/kvrxcqv8/2 . React.DOM.div, giống như tất cả các thành phần cốt lõi, sử dụng childrenmảng. Hãy xem cách nó được sử dụng trong Hellothành phần của bạn , nó đã sử dụng nhiều trẻ em rồi.
Ross Allen

20
Nhược điểm của việc tiếp tục thảo luận trong trò chuyện là họ không được lưu trữ cho độc giả trong tương lai.
ultrafez

3

Cuối trò chơi, nhưng đây là một mẫu HOC mạnh mẽ để ghi đè một thành phần bằng cách cung cấp nó như một chỗ dựa. Thật đơn giản và thanh lịch.

Giả sử MyComponentkết xuất một Athành phần hư cấu nhưng bạn muốn cho phép ghi đè tùy chỉnh A, trong ví dụ này B, nó bao bọc Atrong một <div>...</div>và cũng nối thêm "!" để chống đỡ văn bản:

import A from 'fictional-tooltip';

const MyComponent = props => (
  <props.A text="World">Hello</props.A>
);
MyComponent.defaultProps = { A };

const B = props => (
  <div><A {...props} text={props.text + '!'}></div>
);

ReactDOM.render(<MyComponent A={B}/>);

1

Trên thực tế, câu hỏi của bạn là làm thế nào để viết Thành phần bậc cao (HOC). Mục tiêu chính của việc sử dụng HOC là ngăn chặn việc sao chép. Bạn có thể viết HOC của bạn như là một thành phần chức năng thuần túy hoặc là một lớp ở đây là một ví dụ:

    class Child extends Component {
    render() {
        return (
            <div>
                Child
            </div>
        );
    }
}

Nếu bạn muốn viết thành phần cha mẹ của bạn như là một thành phần dựa trên lớp:

    class Parent extends Component {
    render() {
        return (
            <div>
                {this.props.children}
            </div>
        );
    }
}

Nếu bạn muốn viết cha mẹ của bạn như là một thành phần chức năng:

    const Parent=props=>{
    return(
        <div>
            {props.children}
        </div>
    )
}

0

Dưới đây là một ví dụ về thành phần phản ứng Danh sách cha mẹ và các đạo cụ có chứa phần tử phản ứng. Trong trường hợp này, chỉ một thành phần phản ứng Liên kết duy nhất được truyền vào (như được thấy trong kết xuất dom).

class Link extends React.Component {
  constructor(props){
    super(props);
  }
  render(){
    return (
      <div>
        <p>{this.props.name}</p>
      </div>
     );
  }
}
class List extends React.Component {
  render(){
   return(
    <div>
       {this.props.element}
       {this.props.element}
    </div>
   );
  }
}

ReactDOM.render(
  <List element = {<Link name = "working"/>}/>,
  document.getElementById('root')
);

0

Có, bạn có thể làm điều đó bằng cách sử dụng đạo cụ, bạn có thể truyền dữ liệu của thành phần dưới dạng đối tượng như đạo cụ và sau đó bên trong thành phần bạn có thể nhập thành phần khác và tự động liên kết với dữ liệu prpps. đọc thêm về thành phần phản ứng


1
bạn có thể giải thích với một số mã từ liên kết bạn đã đăng
Nelles
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.