วิธีที่ถูกต้องในการสืบทอดส่วนประกอบ React

ฉันเข้าใจว่าคำถามของฉันค่อนข้างลำเอียงเล็กน้อย แต่ฉันยังใหม่มากใน Javascript และ prototypes และฉันอ่านมาแล้ว แต่ฉันไม่เข้าใจจริงๆ ว่าจะนำเทคนิคนั้นไปใช้กับปัญหาเชิงปฏิบัติได้อย่างไร ตัวอย่างจะเป็นประโยชน์มาก ฉันมีองค์ประกอบ React ซึ่งโดยพื้นฐานแล้วดูเหมือนว่า:

var Component1 = React.createClass({

getInitialState: function () {
        return ({
            searchable: true,
        })
    },

function1: function () {
        return ({
            somevalue
        })
    },

render: function () {

        var redText = {
            color: 'red'
        };

        var redBorder = {
            color: 'red',
            border: '1px solid red'

        };

        return (
                <form>
                    <div>
                        <a onClick={this.props.handleAddClick}>Something</a>
                    </div>

                    <div>
                        <label>Some label</label>
                        <input type="text"/>
                    </div>
               </form> ) 
});

ฉันยังมี Component2 ซึ่งโดยพื้นฐานแล้วเหมือนกันทุกประการ แต่มี <input/> เพิ่มเติมอีกหนึ่งรายการใน return ของฟังก์ชัน render

ฉันยังมี Component3 ซึ่งใช้ฟังก์ชันเดียวกัน แต่มีฟังก์ชัน render() ที่แตกต่างกัน

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

แก้ไข 1____________________________________________________ ดังนั้นฉันจึงพยายามใช้การสืบทอด Prototype ตามคำตอบแรก แต่ดูเหมือนว่า React จะไม่เห็นฟังก์ชันเหล่านี้: getInitialState() เป็นโมฆะ สถานะเริ่มต้นเป็นโมฆะหลังจากการเรนเดอร์ เกิดอะไรขึ้นกับแนวทางนี้?

ฉันพยายามทำตามตำราเรียนและทำ:

function MyPrototype() {};
MyPrototype.prototype.getInitialState = function () {
    return ({
        someProperty: true;
    })
};

function Component1() {};
Component1.prototype = Object.create(MyPrototype.prototype);
Component1.prototype.render = function () {
    console.log(this);
    return (<div></div>)};

var MyComponent1 = React.createClass(new Component1());

แต่เมื่อฉันเปิดเบราว์เซอร์ ฉันได้รับข้อผิดพลาด: Uncaught Invariant Violation: createClass(...): Class specification must implement arendermethod.

ฉันทำอะไรผิดด้วยวิธีนี้?

แก้ไข2_______________________________________________

จริงๆ แล้ว ฉันเห็นว่า React ไม่รองรับมิกซ์อินทั้งต้นแบบ ควรใช้องค์ประกอบแทน มีการอธิบายไว้ในบทความนี้: แดน บทความของ Abramov Mixins Are Dead องค์ประกอบที่มีชีวิตชีวา


person Battle_Slug    schedule 02.05.2016    source แหล่งที่มา


คำตอบ (1)


ใน React การสืบทอดส่วนประกอบต่างๆ ท้อแท้อย่างยิ่ง
React เหมาะกว่ามากสำหรับการแสดงความสัมพันธ์เดียวกันผ่านการเรียบเรียง

นี่คือตัวอย่างการใช้องค์ประกอบ:

class Button extends Component {
  render() {
    return (
      <div className='Button' style={{ color: this.props.color }}>
        {this.props.children}
      </div>
    )
  }
}

class DeleteButton extends Component {
  render() {
    return (
      <Button color='red'>Delete</Button>
    )
  }
}

สังเกตว่า DeleteButton ใช้รูปลักษณ์ของ Button โดยไม่สืบทอด จากรูปลักษณ์นั้นอย่างไร แต่ Button จะกำหนดส่วนที่กำหนดค่าได้ผ่านทาง props และ DeleteButton จะเป็นผู้จัดหาอุปกรณ์ประกอบฉากเหล่านั้น ใน DOM จริง ทั้ง <Button /> และ <DeleteButton /> จะเรนเดอร์ไปยังโหนด DOM เดียว การแก้ปัญหาแบบเรียกซ้ำจะเกิดขึ้นในเวลา render() และนี่คือแนวคิดหลักของ React

ในความเป็นจริง หากคุณไม่ต้องการ hook วงจรการใช้งานหรือสถานะท้องถิ่น คุณยังสามารถกำหนดส่วนประกอบเป็นฟังก์ชันได้:

function Button({ color, children }) {
  return (
    <div className='Button' style={{ color }}>
      {children}
    </div>
  )
}

function DeleteButton() {
  return (
    <Button color='red'>Delete</Button>
  )
}

คุณสามารถผสมคลาสเข้ากับฟังก์ชันได้ สิ่งนี้คงเป็นไปไม่ได้หากได้รับมรดก แต่ใช้งานได้ดีกับการจัดองค์ประกอบภาพ

สำหรับกรณีการใช้งานเฉพาะของคุณ:

ฉันยังมี Component2 ซึ่งโดยพื้นฐานแล้วเหมือนกันทุกประการ แต่มี <input/> เพิ่มเติมอีกหนึ่งรายการในการส่งคืนฟังก์ชันการเรนเดอร์

คุณสามารถให้ Component1 ยอมรับ this.props.children และใช้ในค่าส่งคืนของเมธอด render() และให้ Component2 แสดงผลเป็น <Component1><input /></Component> นี่คล้ายกับสิ่งที่ฉันแสดงไว้ข้างต้นมาก คุณไม่จำเป็นต้องใช้เสา children คุณสามารถส่งองค์ประกอบ React ในเสาใดก็ได้ เช่น <Component1 footer={<input />} /> จากนั้นคุณสามารถใช้ this.props.footer ภายใน Component1

ฉันยังมี Component3 ซึ่งใช้ฟังก์ชันเดียวกัน แต่มีฟังก์ชัน render() ที่แตกต่างกัน

หากพวกเขาแชร์โค้ดอื่นใด (เช่น โปรแกรมอรรถประโยชน์ที่คำนวณข้อมูลบางอย่าง) ให้ย้ายโค้ดนั้นไปนอกคอมโพเนนต์ไปยังโมดูลที่ใช้ร่วมกัน และนำเข้าจากคอมโพเนนต์ทั้งสอง

หากพวกเขาแชร์ UI ใดๆ ให้แยกมันออกเป็นส่วนประกอบอื่น และใช้จากส่วนประกอบทั้งสองของคุณ

person Dan Abramov    schedule 03.05.2016
comment
ไม่น่าเชื่อ คุณตอบโพสต์ของฉันแล้ว :) วันนี้ฉันพบบทความของคุณแล้วและมีข้อพิสูจน์ที่เหมือนกัน ดังนั้นการนั่งเล่นซอกับการจัดองค์ประกอบในคืนนี้ แค่ต้องการตัวอย่างเชิงปฏิบัติเพิ่มเติมอีกสองสามตัวอย่าง ขอบคุณสำหรับคำอธิบายนี้และสำหรับงานของคุณ! ฉันใช้ Redux อย่างกว้างขวางและฉันก็พอใจกับมันมาก - person Battle_Slug; 03.05.2016
comment
โดยปกติแล้วฉันจะแยกส่วนประกอบออกอย่างกว้างขวาง ดังนั้นโค้ดของฉันจึงไม่ทำซ้ำส่วน render สิ่งที่ฉันต้องการคือวิธีการแชร์รหัสเดียวกันสำหรับ getInitialState และฟังก์ชันอื่นๆ ที่เหมือนกัน นั่นคือสิ่งที่ฉันกำลังพยายามตอนนี้ - person Battle_Slug; 03.05.2016
comment
กรณีการใช้งานของคุณสำหรับการแชร์โค้ดใน getInitialState คืออะไร - person Dan Abramov; 06.05.2016
comment
จริงๆ แล้ว ฉันทำสิ่งที่คุณพูดแล้ว: ฉันมี SharedComponent อยู่บ้าง ดังนั้นฉันจึงส่งต่อเด็กๆ ให้มีหน้าที่ของตัวเอง มันใช้งานได้ดี รหัสไม่ซ้ำกัน นอกจากลูกๆ นี้แล้ว ฉันยังมีแฟล็กสากลในสถานะร้านค้า redux SharedComponent แสดงผลขึ้นอยู่กับแฟล็กเหล่านั้น นอกจากนี้ยังเลือกตัวจัดการ onClick ตัวใดสำหรับปุ่มบางปุ่มที่จะใช้โดยพิจารณาจากแฟล็กเหล่านั้นภายในสถานะ redux นี่เป็นวิธีที่ถูกต้องใช่ไหม? รหัสไม่ซ้ำ และฉันมีองค์ประกอบที่นี่ - person Battle_Slug; 06.05.2016