Bagaimana cara memasukkan komponen reaksi ke komponen reaksi lain untuk mentransklusikan konten komponen pertama?

215

Apakah ada cara untuk melewatkan satu komponen ke komponen reaksi lainnya? Saya ingin membuat model komponen reaksi dan mengirimkan komponen reaksi lain untuk mentransklusikan konten itu.

Sunting: Ini adalah kode reaksiJS yang menggambarkan apa yang saya coba lakukan. http://codepen.io/aallbrig/pen/bEhjo

HTML

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

ReactJS

/**@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'));
Andrew Allbright
sumber

Jawaban:

197

Anda dapat menggunakan this.props.childrenuntuk membuat apa pun yang berisi komponen anak-anak:

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

export default () => <Wrap><h1>Hello word</h1></Wrap>
David Hellsing
sumber
4
Saya akan menggunakan jawaban ini. this.props.childrenadalah bagian dari komponen API dan diharapkan dapat digunakan dengan cara ini. Contoh-contoh tim Bereaksi menggunakan teknik ini, seperti dalam mentransfer alat peraga dan ketika berbicara tentang seorang anak tunggal .
Ross Allen
Dari komentar saya di bawah ini: Dengan meneruskannya sebagai prop, Anda bahkan dapat memberikannya nama dan menggunakan propTypes untuk mengetik cek.
returneax
1
@AndrewAllbright: Teladan Anda tidak melewati anak-anak. Ini berfungsi: codepen.io/ssorallen/pen/Dyjmk
Ross Allen
Dan jika Anda kemudian ingin mendapatkan
NAMA
124

Catatan saya memberikan jawaban yang lebih mendalam di sini

Pembungkus Runtime:

Itu cara yang paling idiomatis.

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

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

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

Perhatikan bahwa itu childrenadalah "prop khusus" dalam Bereaksi, dan contoh di atas adalah gula sintaksis dan (hampir) setara dengan<Wrapper children={<App/>}/>


Pembungkus inisialisasi / HOC

Anda dapat menggunakan Komponen Pesanan Tinggi (HOC). Mereka telah ditambahkan ke dokumen resmi baru-baru ini.

// 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);

Hal ini dapat menyebabkan (sedikit) kinerja yang lebih baik karena komponen pembungkus dapat membuat hubungan pendek rendering selangkah lebih maju dengan shouldComponentUpdate, sementara dalam kasus pembungkus runtime, anak-anak cenderung akan selalu menjadi ReactElement yang berbeda dan menyebabkan pengubahan ulang. bahkan jika komponen Anda memperpanjang PureComponent.

Perhatikan bahwa connectRedux dulu merupakan pembungkus runtime tetapi diubah menjadi HOC karena memungkinkan untuk menghindari rendering ulang yang tidak berguna jika Anda menggunakan pureopsi (yang benar secara default)

Anda seharusnya tidak pernah memanggil HOC selama fase render karena membuat komponen Bereaksi bisa mahal. Anda sebaiknya memanggil pembungkus ini saat inisialisasi.


Perhatikan bahwa ketika menggunakan komponen fungsional seperti di atas, versi HOC tidak memberikan optimasi yang berguna karena komponen fungsional stateless tidak diimplementasikan shouldComponentUpdate

Penjelasan lebih lanjut di sini: https://stackoverflow.com/a/31564812/82609

Sebastien Lorber
sumber
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} />
Joseph Barnes
sumber
Ini akan menjadi benar jika ... Bereaksi 15.x melarang Anda untuk mengembalikan komponen multi-simpul. Bereaksi 16 (alias Bereaksi Serat) akan memungkinkan banyak node. Inilah perbaikan untuk contoh kode Anda: const ParentComponent = (props) => ({props.childComponent}); impor MyComponent dari //...where const myComponent = <MyComponent /> // lulus sebagai prop <ParentComponent childComponent = {myComponent} />
Andrew Allbright
13

Facebook merekomendasikan penggunaan komponen berkewarganegaraan Sumber: https://facebook.github.io/react/docs/reusable-components.html

Dalam dunia yang ideal, sebagian besar komponen Anda akan menjadi fungsi stateless karena di masa depan kami juga akan dapat membuat optimasi kinerja yang spesifik untuk komponen-komponen ini dengan menghindari pemeriksaan dan alokasi memori yang tidak perlu. Ini adalah pola yang disarankan, bila memungkinkan.

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);
Sud
sumber
13

Anda dapat melewatinya sebagai penyangga biasa: foo={<ComponentOne />}

Sebagai contoh:

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

saya lebih suka menggunakan Bereaksi API bawaan:

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
};

maka Anda dapat mengganti div pembungkus dengan apa pun yang Anda inginkan:

<Test wrapper={<span className="LOL"/>}>
  <div>child1</div>
  <div>child2</div>
</Test> 
Fareed Alnamrouti
sumber
5

Anda dapat mengirimkan komponen melalui. alat peraga dan membuatnya dengan interpolasi.

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

Anda kemudian akan melewati propdipanggil child, yang akan menjadi komponen Bereaksi.

returneax
sumber
1
Ini akan menyebabkan melewati komponen melalui atribut daripada sebagai anak-anak. Jika Anda menggunakan this.props.childrenseperti yang disarankan dalam jawaban lain, Anda dapat menulis anak-anak sebagai anak-anak bukan attrs.
Ross Allen
1
@sallallen Anda tidak mengatakan mengapa seseorang lebih baik dengan cara apa pun ... Dengan melewatkannya sebagai alat peraga Anda bahkan dapat memberikan nama dan menggunakan propTip untuk mengetik centang.
returneax
1
Setiap elemen yang Anda gunakan di JSX hanyalah komponen. Jika mereka menggunakan pendekatan ini, Anda tidak akan bisa menulis bahkan contoh singkat Anda. Itu akan menjadi <div child={this.props.child />.
Ross Allen
1
Lihat versi JavaScript (apa yang diubah oleh JSX): jsfiddle.net/ssorallen/kvrxcqv8/2 . React.DOM.div, seperti semua komponen inti, menggunakan childrenarray. Lihatlah bagaimana ini digunakan dalam Hellokomponen Anda , ia sudah menggunakan beberapa anak.
Ross Allen
20
Kelemahan dari melanjutkan diskusi dalam obrolan adalah bahwa mereka tidak diarsipkan untuk pembaca masa depan.
ultrafez
3

Terlambat dalam permainan, tapi inilah pola HOC yang kuat untuk menimpa komponen dengan menyediakannya sebagai penyangga. Sederhana dan elegan.

Misalkan MyComponentmerender Akomponen fiksi tetapi Anda ingin membolehkan penimpaan kustom A, dalam contoh ini B, yang membungkus Adalam <div>...</div>dan juga menambahkan "!" ke prop teks:

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}/>);
Joneit
sumber
1

Sebenarnya, pertanyaan Anda adalah bagaimana cara menulis Komponen Tingkat Tinggi (HOC). Tujuan utama menggunakan HOC adalah mencegah copy paste. Anda dapat menulis HOC Anda sebagai komponen yang berfungsi murni atau sebagai kelas di sini adalah contoh:

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

Jika Anda ingin menulis komponen induk Anda sebagai komponen berbasis kelas:

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

Jika Anda ingin menulis orang tua Anda sebagai komponen fungsional:

    const Parent=props=>{
    return(
        <div>
            {props.children}
        </div>
    )
}
Meisam Nazari
sumber
0

Berikut adalah contoh komponen Daftar reaksi induk dan alat peraga siapa yang berisi elemen reaksi. Dalam hal ini, hanya satu link bereaksi komponen dilewatkan (seperti terlihat dalam dom render).

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')
);
keju
sumber
0

Ya, Anda dapat melakukannya dengan menggunakan alat peraga. Anda dapat mengirimkan data komponen sebagai objek seperti alat peraga dan kemudian di dalam komponen Anda dapat mengimpor komponen lain dan secara dinamis mengikat dengan data prpps. baca lebih lanjut tentang komponen reaksi

Dipankar Dutta
sumber
1
dapatkah Anda menguraikan beberapa kode dari tautan yang Anda poskan
Nelles