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 개의 경고가 표시되고 후속 질문이 있습니다.

오류 : 포착되지 않은 TypeError : null의 'otherChecked'속성을 읽을 수 없습니다.

경고 : getInitialState는 일반 JavaScript 클래스 인 RadioOther에 정의되었습니다. 이것은 React.createClass를 사용하여 생성 된 클래스에 대해서만 지원됩니다. 대신 상태 속성을 정의하려고 했습니까?


  1. 누구든지 오류가있는 곳을 볼 수 있습니다. DOM의 조건문 때문이라는 것을 알지만 초기 값을 올바르게 선언하지 않은 것 같습니다.

  2. getInitialState를 정적으로 만들어야합니까?

  3. getInitialState가 올바르지 않은 경우 내 proptype을 선언 할 적절한 위치는 어디입니까?

최신 정보:

   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}, 와 같은 함수를 전달할 thisonRadChange호출 될 때 인스턴스를 참조하지 않습니다 . 콜백을 바인딩 render하거나 생성자에서 수행해야합니다 onChange={this.onRadChange.bind(this)}..
Ross Allen

답변:


239
  • getInitialStateES6 클래스에서는 사용되지 않습니다. 대신 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 = () => {
    ...
  };

  ...

}

ES6 Classes : Converting a Function to a Class 에 대한 React의 문서를 더보세요.


1 년이 지나면 다음과 같은 결과를 얻을 수 있습니다. Uncaught TypeError: Cannot read property 'bind' of undefined오류 아이디어가 있습니까?
Jamie Hutber

@JamieHutber 코드로 새 질문을 만들 수 있습니까? 메서드가 클래스에 정의되어 있으면 해당 오류가 발생하는 이유를 모르겠습니다.
로스 알렌

제안 해 주셔서 감사합니다, @KennethWorden. React 문서에 대한 이슈를 열었습니다 : github.com/facebook/react/issues/7746
Ross Allen

'제자리에 바인딩'은 위에 표시된 화살표 기능을 사용한다는 의미입니까? 물론 작동합니다. 아, 자바 스크립트!
jomofrodo

@jomofrodo 모호합니다. 지적 해 주셔서 감사합니다. 나는 render당신이 같은 onClick={this.doFoo.bind(this)}일 을 할 수 있다는 것을 의미 했지만, render자주 호출 될 수 있고 각 호출에서 새로운 함수를 생성 할 수 있기 때문에 바인딩하는 가장 효율적인 방법이기 때문에 의도적으로 코드에 포함하지 않았습니다 . 답변에서 해당 언어를 제거하겠습니다.
Ross Allen

4

로스에 추가 대답에 .

새로운 ES6 화살표 기능을 사용할 수도 있습니다.onChange 속성 을

정의하는 것과 기능적으로 동일합니다. this.onRadChange = this.onRadChange.bind(this);생성자에서 하지만 제 생각에는 더 간결합니다.

귀하의 경우 라디오 버튼은 다음과 같습니다.

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

최신 정보

이 "더 간결한"방법은 render()메서드가 호출 될 때마다 새 함수를 생성하기 때문에 @Ross Allen의 답변에 언급 된 옵션보다 덜 효율적 입니다.


1
이 솔루션은 기능적으로 정확하지만 render(여러 번 호출 될 수있는) 각 호출에 대해 새 함수를 만듭니다 . 생성자에서 클래스 속성 이니셜 라이저 또는 바인딩을 사용하면 구성 요소 생성시 하나의 새로운 바인딩 된 함수 만 생성되고 render.
Ross Allen

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.