React, ES6 - getInitialState ถูกกำหนดบนคลาส JavaScript ธรรมดา


115

ฉันมีส่วนประกอบต่อไปนี้ ( radioOther.jsx):

 'use strict';

 //module.exports = <-- omitted in update

   class RadioOther extends React.Component {

     // omitted in update 
     // getInitialState() {
     //    propTypes: {
     //        name: React.PropTypes.string.isRequired
     //    }
     //    return {
     //       otherChecked: false
     //   }
     // }

     componentDidUpdate(prevProps, prevState) {
         var otherRadBtn = this.refs.otherRadBtn.getDOMNode();

         if (prevState.otherChecked !== otherRadBtn.checked) {
             console.log('Other radio btn clicked.')
             this.setState({
                 otherChecked: otherRadBtn.checked,
             });
         }
     }

     onRadChange(e) {
         var input = e.target;
         this.setState({
             otherChecked: input.checked
         });
     }

     render() {
         return (
             <div>
                 <p className="form-group radio">
                     <label>
                         <input type="radio"
                                ref="otherRadBtn"
                                onChange={this.onRadChange}
                                name={this.props.name}
                                value="other"/>
                         Other
                     </label>
                     {this.state.otherChecked ?
                         (<label className="form-inline">
                             Please Specify:
                             <input
                                 placeholder="Please Specify"
                                 type="text"
                                 name="referrer_other"
                                 />
                         </label>)
                         :
                         ('')
                     }
                 </p>
             </div>
         )
     }
 };

ก่อนที่จะใช้ ECMAScript6 ทุกอย่างเป็นไปด้วยดีตอนนี้ฉันได้รับ 1 ข้อผิดพลาด 1 คำเตือนและฉันมีคำถามติดตาม:

ข้อผิดพลาด: Uncaught TypeError: ไม่สามารถอ่านคุณสมบัติ 'otherChecked' ของ null

คำเตือน: getInitialState ถูกกำหนดบน RadioOther ซึ่งเป็นคลาส JavaScript ธรรมดา รองรับเฉพาะคลาสที่สร้างโดยใช้ React.createClass คุณหมายถึงการกำหนดทรัพย์สินของรัฐแทนหรือไม่?


  1. ทุกคนสามารถเห็นว่าข้อผิดพลาดอยู่ที่ใดฉันรู้ว่าเกิดจากคำสั่งเงื่อนไขใน DOM แต่ดูเหมือนว่าฉันไม่ได้ประกาศค่าเริ่มต้นอย่างถูกต้อง

  2. ฉันควรทำให้getInitialStateคงที่หรือไม่

  3. สถานที่ที่เหมาะสมในการประกาศ proptypes ของฉันอยู่ที่ไหนหาก getInitialState ไม่ถูกต้อง

UPDATE:

   RadioOther.propTypes = {
       name: React.PropTypes.string,
       other: React.PropTypes.bool,
       options: React.PropTypes.array }

   module.exports = RadioOther;

@ssorallen รหัสนี้:

     constructor(props) {
         this.state = {
             otherChecked: false,
         };
     }

ผลิต"Uncaught ReferenceError: this is not defined"และในขณะที่ด้านล่างแก้ไขสิ่งนั้น

     constructor(props) {
     super(props);
         this.state = {
             otherChecked: false,
         };
     }

แต่ตอนนี้การคลิกปุ่มอื่นทำให้เกิดข้อผิดพลาด:

Uncaught TypeError: Cannot read property 'props' of undefined


1
การเปลี่ยนแปลงอื่น ๆ สำหรับการเรียน ES6 เป็นว่าวิธีการไม่ได้ "อัตโนมัติผูกพัน" อินสแตนซ์ที่มีความหมายเมื่อคุณผ่านฟังก์ชั่นเช่นonChange={this.onRadChange}, thisไม่ได้หมายถึงตัวอย่างเช่นเมื่อonRadChangeถูกเรียกว่า คุณจำเป็นต้องเรียกกลับผูกในหรือทำมันในตัวสร้าง:render onChange={this.onRadChange.bind(this)}
Ross Allen

คำตอบ:


239
  • getInitialStateไม่ได้ใช้ในคลาส ES6 แทนที่จะกำหนดthis.stateในตัวสร้าง
  • propTypes ควรเป็นตัวแปรคลาสแบบคงที่หรือกำหนดให้กับคลาสจึงไม่ควรกำหนดให้กับอินสแตนซ์คอมโพเนนต์
  • เมธอดสมาชิกไม่ใช่"ผูกอัตโนมัติ"ในคลาส ES6 สำหรับวิธีที่ใช้เป็นการเรียกกลับให้ใช้ตัวเริ่มต้นคุณสมบัติคลาสหรือกำหนดอินสแตนซ์ที่ถูกผูกไว้ในตัวสร้าง
export default class RadioOther extends React.Component {

  static propTypes = {
    name: React.PropTypes.string.isRequired,
  };

  constructor(props) {
    super(props);
    this.state = {
      otherChecked: false,
    };
  }

  // Class property initializer. `this` will be the instance when
  // the function is called.
  onRadChange = () => {
    ...
  };

  ...

}

ดูเพิ่มเติมในเอกสารของ React เกี่ยวกับคลาส ES6: การแปลงฟังก์ชันเป็นคลาส


หนึ่งปีต่อมาคุณอาจพบว่าคุณได้รับ: Uncaught TypeError: Cannot read property 'bind' of undefinedข้อผิดพลาดความคิดใด ๆ ?
Jamie Hutber

@JamieHutber คุณสามารถสร้างคำถามใหม่ด้วยรหัสของคุณได้หรือไม่? หากกำหนดวิธีการในคลาสฉันไม่รู้ว่าทำไมคุณถึงได้รับข้อผิดพลาดนั้น
Ross Allen

ขอบคุณสำหรับคำแนะนำ @KennethWorden ฉันเปิดปัญหาสำหรับเอกสาร React: github.com/facebook/react/issues/7746
Ross Allen

'ผูกเข้าที่' หมายความว่าใช้ฟังก์ชันลูกศรตามที่คุณแสดงด้านบนหรือไม่ แน่นอนว่าได้ผล โอ้จาวาสคริปต์!
jomofrodo

@jomofrodo ไม่ชัดเจนขอบคุณที่ชี้ให้เห็น ฉันหมายความว่าrenderคุณสามารถทำบางอย่างเช่นonClick={this.doFoo.bind(this)}แต่ฉันตั้งใจไม่รวมไว้ในรหัสเพราะนั่นเป็นวิธีที่มีประสิทธิภาพน้อยที่สุดในการผูกเนื่องจากrenderอาจถูกเรียกบ่อยครั้งและจะสร้างฟังก์ชันใหม่ในการโทรแต่ละครั้ง ฉันจะลบภาษานั้นออกจากคำตอบ
Ross Allen

4

เพิ่มคำตอบของ Ross

คุณยังสามารถใช้ฟังก์ชันลูกศร ES6ใหม่บนคุณสมบัติ onChange

มันมีหน้าที่เทียบเท่ากับการกำหนดthis.onRadChange = this.onRadChange.bind(this);ในตัวสร้าง แต่มีความกระชับมากกว่าในความคิดของฉัน

ในกรณีของคุณปุ่มตัวเลือกจะมีลักษณะดังต่อไปนี้

<input type="radio"
       ref="otherRadBtn"
       onChange={(e)=> this.onRadChange(e)}
       name={this.props.name}
       value="other"/>

ปรับปรุง

วิธีการที่ "รัดกุมกว่า" นี้มีประสิทธิภาพน้อยกว่าตัวเลือกที่กล่าวถึงในคำตอบของ @Ross Allen เนื่องจากสร้างฟังก์ชันใหม่ทุกครั้งที่render()เรียกวิธีการ


1
โซลูชันนี้ถูกต้องตามหน้าที่ แต่จะสร้างฟังก์ชันใหม่ในการเรียกแต่ละครั้งrender(ซึ่งสามารถเรียกได้หลายครั้ง) โดยใช้ initializer renderคุณสมบัติชั้นเรียนหรือมีผลผูกพันในการสร้างเพียงหนึ่งฟังก์ชั่นที่ถูกผูกไว้ใหม่จะถูกสร้างขึ้นในการก่อสร้างของส่วนประกอบและไม่มีฟังก์ชั่นใหม่จะถูกสร้างขึ้นในช่วง
Ross Allen

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