วิธีการส่งผ่านส่วนประกอบปฏิกิริยาไปยังส่วนประกอบปฏิกิริยาอื่นเพื่อแปลงเนื้อหาขององค์ประกอบแรกเป็นอย่างไร


216

มีวิธีการส่งผ่านองค์ประกอบหนึ่งไปยังส่วนประกอบปฏิกิริยาอื่นหรือไม่? ฉันต้องการสร้างแบบจำลององค์ประกอบการตอบสนองและส่งผ่านองค์ประกอบการตอบสนองอื่นเพื่อแปลงเนื้อหานั้น

แก้ไข: นี่คือ codepen reactJS แสดงสิ่งที่ฉันพยายามทำ 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'));

คำตอบ:


198

คุณสามารถใช้this.props.childrenเพื่อแสดงสิ่งที่องค์ประกอบของเด็ก ๆ :

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

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

4
ฉันจะใช้คำตอบนี้ this.props.childrenเป็นส่วนหนึ่งของ API ส่วนประกอบและคาดว่าจะใช้วิธีนี้ ตัวอย่างทีมตอบสนองของใช้เทคนิคนี้เช่นในการถ่ายโอนอุปกรณ์ประกอบฉากและเมื่อพูดถึงเด็กคนเดียว
Ross Allen

จากความคิดเห็นของฉันด้านล่าง: โดยผ่านมันเป็นเสาคุณสามารถให้ชื่อและใช้ propTypes เพื่อพิมพ์ตรวจสอบ
returneax

1
@AndrewAllbright: ตัวอย่างของคุณไม่ผ่านลูก ๆ งานนี้: codepen.io/ssorallen/pen/Dyjmk
Ross Allen

และในกรณีที่คุณต้องการได้รับโหนด DOM ของเด็ก ๆ : stackoverflow.com/questions/29568721/ …
ericsoco

124

หมายเหตุฉันให้คำตอบเชิงลึกเพิ่มเติม ที่นี่

เสื้อคลุมรันไทม์:

มันเป็นวิธีที่งี่เง่าที่สุด

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

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

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

โปรดทราบว่าchildrenเป็น "เสาพิเศษ" ใน React และตัวอย่างข้างต้นคือน้ำตาลประโยคและเทียบเท่า (เกือบ)<Wrapper children={<App/>}/>


wrapper การเริ่มต้น / HOC

คุณสามารถใช้ส่วนประกอบการสั่งซื้อที่สูงขึ้น (HOC) พวกเขาถูกเพิ่มไปยังเอกสารอย่างเป็นทางการเมื่อเร็ว ๆ นี้

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

สิ่งนี้สามารถนำไปสู่การแสดงที่ดีขึ้น (เล็กน้อย) เนื่องจากส่วนประกอบของ wrapper สามารถลัดวงจรการเรนเดอร์หนึ่งก้าวไปข้างหน้าด้วย shouldComponentUpdate ในขณะที่ในกรณีของ wrapper รันไทม์เด็ก ๆ prop น่าจะเป็น ReactElement ที่แตกต่างกัน แม้ว่าคอมโพเนนต์ของคุณจะขยาย PureComponent

โปรดสังเกตว่าconnectRedux เคยเป็น wrapper รันไทม์ แต่ถูกเปลี่ยนเป็น HOC เพราะอนุญาตให้หลีกเลี่ยงการแสดงผลซ้ำที่ไร้ประโยชน์หากคุณใช้pureตัวเลือก (ซึ่งเป็นจริงโดยค่าเริ่มต้น)

คุณไม่ควรเรียก HOC ระหว่างขั้นตอนการสร้างภาพเพราะการสร้างองค์ประกอบแบบ React อาจมีราคาแพง คุณควรเรียก wrappers เหล่านี้เมื่อเริ่มต้น


โปรดทราบว่าเมื่อใช้ส่วนประกอบที่ใช้งานได้ด้านบนรุ่น HOC จะไม่มีการปรับให้เหมาะสมที่มีประโยชน์เพราะส่วนประกอบการทำงานที่ไร้สัญชาตินั้นไม่ได้ใช้งาน shouldComponentUpdate

คำอธิบายเพิ่มเติมได้ที่นี่: 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} />

สิ่งนี้จะถูกต้องหากเป็น ... React 15.x ไม่อนุญาตให้คุณส่งคืนคอมโพเนนต์หลายโหนด React 16 (aka React Fiber) จะอนุญาตให้ใช้หลายโหนด นี่คือการแก้ไขสำหรับตัวอย่างรหัสของคุณ: const ParentComponent = (props) => ({props.childComponent}); นำเข้า MyComponent จาก //...where const const myComponent = <MyComponent /> // ผ่านเป็น prop <ParentComponent childComponent = {myComponent} />
แอนดรู

13

Facebook แนะนำการใช้ส่วนประกอบไร้สัญชาติที่มา: https://facebook.github.io/react/docs/reusable-components.html

ในโลกอุดมคติองค์ประกอบส่วนใหญ่ของคุณจะเป็นฟังก์ชันไร้สัญชาติเพราะในอนาคตเราจะสามารถเพิ่มประสิทธิภาพการทำงานเฉพาะสำหรับส่วนประกอบเหล่านี้โดยหลีกเลี่ยงการตรวจสอบและจัดสรรหน่วยความจำที่ไม่จำเป็น นี่คือรูปแบบที่แนะนำเมื่อเป็นไปได้

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

คุณสามารถผ่านมันเป็นเสาปกติ: foo={<ComponentOne />}

ตัวอย่างเช่น:

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

ฉันชอบใช้ React ในตัว API:

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

จากนั้นคุณสามารถแทนที่ div wrapper ด้วยสิ่งที่คุณต้องการ:

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

5

คุณสามารถส่งผ่านส่วนประกอบได้ อุปกรณ์ประกอบฉากและทำให้มันมีการแก้ไข

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

จากนั้นคุณจะผ่านการpropเรียกใช้childซึ่งจะเป็นองค์ประกอบการตอบสนอง


1
สิ่งนี้จะนำไปสู่การส่งผ่านองค์ประกอบต่างๆผ่านคุณลักษณะต่างๆแทนที่จะเป็นลูก หากคุณใช้this.props.childrenตามคำแนะนำในคำตอบอื่นคุณสามารถเขียนเด็ก ๆ เป็นเด็ก ๆ แทนที่จะเป็นผู้ดูแล
Ross Allen

1
@sorallen คุณไม่ได้พูดว่าทำไมถึงดีกว่าในทางใดทางหนึ่ง ... โดยผ่านมันเป็นเสาคุณสามารถตั้งชื่อและใช้ propTypes เพื่อพิมพ์เช็คได้
returneax

1
ทุกองค์ประกอบที่คุณใช้ใน JSX เป็นเพียงองค์ประกอบ หากพวกเขาใช้วิธีนี้คุณจะไม่สามารถเขียนแม้แต่ตัวอย่างสั้น ๆ ของคุณ <div child={this.props.child />มันจะกลายเป็น
Ross Allen

1
ตรวจสอบรุ่น JavaScript (สิ่ง JSX เปลี่ยนมันเป็น): jsfiddle.net/ssorallen/kvrxcqv8/2 React.DOM.divเช่นเดียวกับองค์ประกอบหลักทั้งหมดใช้childrenอาร์เรย์ ดูว่ามันถูกใช้ในHelloอุปกรณ์ของคุณอย่างไรโดยใช้ลูกหลายคน
Ross Allen

20
ข้อเสียของการสนทนาในแชทต่อเนื่องคือพวกเขาจะไม่ถูกเก็บถาวรสำหรับผู้อ่านในอนาคต
ultrafez

3

มาถึงช่วงท้ายเกม แต่นี่เป็นรูปแบบ HOC ที่ทรงพลังสำหรับการเอาชนะส่วนประกอบโดยการจัดให้มันเป็นเสา มันง่ายและสง่างาม

สมมติว่าMyComponentแสดงAส่วนประกอบสมมติแต่คุณต้องการอนุญาตให้มีการแทนที่แบบกำหนดเองAในตัวอย่างนี้Bซึ่งล้อมรอบAด้วย a <div>...</div>และผนวก "!" เพื่อ prop ข้อความ:

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

ที่จริงแล้วคำถามของคุณคือวิธีการเขียนส่วนประกอบคำสั่งซื้อที่สูงขึ้น (HOC) เป้าหมายหลักของการใช้ HOC คือการป้องกันการคัดลอก คุณสามารถเขียน HOC ของคุณเป็นองค์ประกอบที่ใช้งานได้อย่างหมดจดหรือเป็นตัวอย่างในชั้นเรียน:

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

ถ้าคุณต้องการที่จะเขียนองค์ประกอบหลักของคุณเป็นองค์ประกอบตามระดับ:

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

หากคุณต้องการที่จะเขียนผู้ปกครองของคุณเป็นองค์ประกอบการทำงาน:

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

0

นี่คือตัวอย่างขององค์ประกอบหลักของรายการปฏิกิริยาและประกอบฉากที่มีองค์ประกอบตอบสนอง ในกรณีนี้จะมีการส่งผ่านส่วนประกอบการตอบสนองลิงก์เดียว(ตามที่เห็นในการแสดงผล 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

ใช่คุณสามารถทำได้โดยใช้อุปกรณ์ประกอบฉากที่คุณสามารถส่งผ่านข้อมูลของส่วนประกอบเป็นวัตถุเช่นอุปกรณ์ประกอบฉากและจากนั้นภายในองค์ประกอบที่คุณสามารถนำเข้าส่วนประกอบอื่นและผูกแบบไดนามิกกับข้อมูล prpps อ่านเพิ่มเติมเกี่ยวกับองค์ประกอบการตอบสนอง


1
คุณสามารถทำอย่างละเอียดด้วยรหัสจากลิงค์ที่คุณโพสต์
Nelles
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.