반응-catch되지 않은 TypeError : 정의되지 않은 'setState'속성을 읽을 수 없습니다.


316

다음과 같은 오류가 발생합니다

잡히지 않은 TypeError : 정의되지 않은 'setState'속성을 읽을 수 없습니다

생성자에서 델타를 바인딩 한 후에도.

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count : 1
        };

        this.delta.bind(this);
    }

    delta() {
        this.setState({
            count : this.state.count++
        });
    }

    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.delta}>+</button>
            </div>
        );
    }
}

4
ES6에서는이 문제를 해결하기 위해 함수 선언에 화살표 함수를 사용할 수 있습니다.
Tal

^ 이것은 정답이어야합니다
11

응답 기능을 ES6으로 변경하고 작동합니다.
Ashwani Garg

답변:


448

this.delta에 바인딩되지 않았기 때문 this입니다.

this.delta = this.delta.bind(this)생성자에서 set을 바인딩하려면 :

constructor(props) {
    super(props);

    this.state = {
        count : 1
    };

    this.delta = this.delta.bind(this);
}

현재 바인드를 호출하고 있습니다. 그러나 bind는 바운드 함수를 반환합니다. 함수를 바인딩 된 값으로 설정해야합니다.


186
메소드에 적절한 어휘 this바인딩이없고 정의에 직접 컨텍스트를 바인딩하기위한 구문을 노출시키지 않으면 ES6 클래스의 요점은 무엇입니까 ?
AgmLauncher

1
나는 당신의 요점을 이해하지만 componentWillMount ()에서 코드를 작성하면 어떻게 바인딩 할 것인가
suresh pareek

1
@sureshpareek 생성자에서 함수를 바인딩 한 후에는 수명주기 후크에서 호출 할 때 바인딩되어야합니다.
Levi Fuller

4
Tudor

3
Lambda 함수의 @AgmLauncher 사용은 암시 적으로 이것을 바인딩합니다. 코드 delta로 정의하면 delta = () => { return this.setState({ count: this.state.count++ }); };작동합니다. 여기에 설명 : hackernoon.com/…
K. Rhoda

144

에서는 ES7 + (ES2016)는 실험 사용할 수 기능 바인드 구문 연산자를 ::바인드한다. 그것은 구문 설탕이며 Davin Tryon의 대답과 똑같이 할 것입니다.

그런 다음 다시 작성할 수 있습니다 this.delta = this.delta.bind(this);this.delta = ::this.delta;


들어 ES6 + (ES2015) 당신은 또한 ES6를 사용 + 수있는 기능을 화살표 ( =>사용할 수 있도록) this.

delta = () => {
    this.setState({
        count : this.state.count + 1
    });
}

왜 ? Mozilla 문서에서 :

화살표 함수까지 모든 새로운 함수는 자체적 으로이 값을 정의했습니다 [...]. 이것은 객체 지향 스타일의 프로그래밍으로 성가신 것으로 판명되었습니다.

화살표 함수 는 둘러싼 컨텍스트 의이 값을 캡처합니다 ...]


3
이것을 자세히 설명하는 멋진 기사 : reactkungfu.com/2015/07/…
Edo

구문 외에 다른 것을 사용하는 것의 장점은 무엇입니까?
Jeremy D

2
바인드 구문은 메소드의 정상적인 범위를 유지할 수 있으므로 더 깨끗합니다.
Fabien Sa

바인드 구문은 ES2016 또는 ES2017의 일부가 아닙니다.
Felix Kling

2
@stackoverflow는 모든 답변에 현상금을 추가하는 기능을 추가해야합니다.
Gabe

29

ES5와 ES6 클래스 사이에는 컨텍스트가 다릅니다. 따라서 구현 사이에도 약간의 차이가 있습니다.

ES5 버전은 다음과 같습니다.

var Counter = React.createClass({
    getInitialState: function() { return { count : 1 }; },
    delta: function() {
        this.setState({
            count : this.state.count++
        });
    },
    render: function() {
        return (
            <div>
              <h1>{this.state.count}</h1>
              <button onClick={this.delta}>+</button>
            </div>
            );
    }
});

그리고 여기 ES6 버전이 있습니다 :

class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = { count : 1 };
    }

    delta() {
        this.setState({
            count : this.state.count++
        });
    }

    render() {
        return (
            <div>
              <h1>{this.state.count}</h1>
              <button onClick={this.delta.bind(this)}>+</button>
            </div>
            );
    }
}

클래스 구현의 구문 차이 외에도 이벤트 핸들러 바인딩에 차이가 있습니다.

ES5 버전에서는

              <button onClick={this.delta}>+</button>

ES6 버전에서는 다음과 같습니다.

              <button onClick={this.delta.bind(this)}>+</button>

JSX에서 화살표 함수 또는 바인딩을 사용하는 것은 나쁜 습관입니다. stackoverflow.com/questions/36677733/... .
Fabien Sa

24

React에서 ES6 코드를 사용할 때는 항상 화살표 기능을 사용하십시오. 컨텍스트는 자동으로 바인딩되므로

이것을 사용하십시오 :

(videos) => {
    this.setState({ videos: videos });
    console.log(this.state.videos);
};

대신에:

function(videos) {
    this.setState({ videos: videos });
    console.log(this.state.videos);
};

2
화살표 기능을 사용하고 파라미터 변수키 변수 와 동일 하다면 , 다음과 같이 사용하는 것이 좋습니다 this.setState({videos});
jayeshkv

이것이 나를 위해 한 일입니다. 나는 노드를 처음 사용했고,
axios

20

당신은 아무것도 바인딩 할 필요가 없습니다. 다음과 같이 Arrow 함수를 사용하십시오.

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count: 1
        };

    }
    //ARROW FUNCTION
    delta = () => {
        this.setState({
            count: this.state.count++
        });
    }

    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.delta}>+</button>
            </div>
        );
    }
}

차이점이 무엇인지 이해하십시오. 왜 그런가요?
Ridha Rezzag 1

4
화살표 기능이있는이 범위는 컨텍스트에서 상속됩니다. 정규 함수를 사용하면 항상 가장 가까운 함수를 참조하지만 화살표 기능을 사용하면이 문제가 제거되고 var that = this를 다시 작성할 필요가 없습니다. @RezzagRidha
가보 루이즈

1
2019 년 현재이 방법은 (Y)
MH

6

다음을 사용할 수도 있습니다.

<button onClick={()=>this.delta()}>+</button>

또는:

<button onClick={event=>this.delta(event)}>+</button>

당신은 몇 가지 매개 변수를 전달하는 경우 ..


JSX에서 화살표 기능을 사용하는 것은 좋지 않습니다
Gabe

5

이것을 생성자에 바인딩하고 생성자에 대한 변경 사항이 서버를 다시 시작해야한다는 것을 기억하십시오. 그렇지 않으면 같은 오류로 끝납니다.


1
서버를 다시 시작하지 않아서 머리를 뽑고있었습니다.
kurtcorbett

5

메소드를 'this'(기본 객체)로 바인딩해야합니다. 따라서 함수가 무엇이든간에 생성자에서 바인딩 할 수 있습니다.

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

    this.handleChecked = this.handleChecked.bind(this);
}

handleChecked(){
    this.setState({
        checked: !(this.state.checked)
    })
}

render(){
    var msg;

    if(this.state.checked){
        msg = 'checked'
    }
    else{
        msg = 'not checked'
    }

    return (
        <div>               
            <input type='checkbox' defaultChecked = {this.state.checked} onChange = {this.handleChecked} />
            <h3>This is {msg}</h3>
        </div>
    );

4

이 오류는 다양한 방법으로 해결할 수 있습니다.

  • ES5 구문을 사용하는 경우 React js Documentation에 따라 bind 메소드 를 사용해야 합니다.

    위 예제에서 이와 같은 것 :

    this.delta = this.delta.bind(this)

  • 당신이 사용하는 경우 ES6의 구문을 다음 사용할 필요가 없다 바인드 방법을, 당신은 이런 식으로 뭔가 함께 할 수 있습니다 :

    delta=()=>{ this.setState({ count : this.state.count++ }); }


2

이 문제에 대한 두 가지 해결책이 있습니다.

첫 번째 해결책은 구성 요소에 생성자를 추가하고 다음과 같이 함수를 바인딩하는 것입니다.

constructor(props) {
        super(props);

        ...

        this.delta = this.delta.bind(this);
    }

이렇게하십시오 :

this.delta = this.delta.bind(this); 

이 대신에 :

this.delta.bind(this);

두 번째 해결책은 대신 화살표 기능을 사용하는 것입니다.

delta = () => {
       this.setState({
           count : this.state.count++
      });
   }

실제로 화살표 함수 자신의 바인딩 하지 않습니다this . 어휘 기능적으로 어휘 bind의 컨텍스트 this원래 컨텍스트를 나타냅니다 .

바인드 함수에 대한 자세한 정보 :

바인드 함수 JavaScript 바인드 이해 ()

화살표 기능에 대한 자세한 정보 :

Javascript ES6 — 화살표 함수 및 어휘 this


1

아래에서 언급 한 것처럼 키워드로 새 이벤트를 바인딩해야 합니다 ...

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count : 1
        };

        this.delta = this.delta.bind(this);
    }

    delta() {
        this.setState({
            count : this.state.count++
        });
    }

    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.delta}>+</button>
            </div>
        );
      }
    }

1

첨가

onClick = {this.delta.bind (this)}

문제를 해결할 것입니다. 이 오류는 ES6 class 함수를 호출하려고 할 때 발생하므로 메소드를 바인딩해야합니다.


1

화살표 기능을 사용 하면이 키워드의 바인딩을 피하기가 더 쉬워 질 수 있습니다 . 이렇게 :

 delta = () => {
       this.setState({
           count : this.state.count++
      });
   }

0

이 질문에 이미 해결책이 있었지만 명확하게하기 위해 공유하고 싶습니다. 도움이 될 수 있기를 바랍니다.

/* 
 * The root cause is method doesn't in the App's context 
 * so that it can't access other attributes of "this".
 * Below are few ways to define App's method property
 */
class App extends React.Component {
  constructor() {
     this.sayHi = 'hello';
     // create method inside constructor, context = this
     this.method = ()=> {  console.log(this.sayHi) };

     // bind method1 in constructor into context 'this'
     this.method1 = this.method.bind(this)
  }

  // method1 was defined here
  method1() {
      console.log(this.sayHi);
  }

  // create method property by arrow function. I recommend this.
  method2 = () => {
      console.log(this.sayHi);
  }
   render() {
   //....
   }
}

0
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>

    <script src="https://unpkg.com/react@0.14.8/dist/react.min.js"></script>
    <script src="https://unpkg.com/react-dom@0.14.8/dist/react-dom.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>

  </head>
  <body>
  <div id="root"></div>
    <script type="text/babel">

        class App extends React.Component{

            constructor(props){
                super(props);
                this.state = {
                    counter : 0,
                    isToggle: false
                }
            this.onEventHandler = this.onEventHandler.bind(this);   
            }

            increment = ()=>{
                this.setState({counter:this.state.counter + 1});
            }

            decrement= ()=>{
                if(this.state.counter > 0 ){
                this.setState({counter:this.state.counter - 1});    
                }else{
                this.setState({counter:0});             
                }
            }
            // Either do it as onEventHandler = () => {} with binding with this  // object. 
            onEventHandler(){
                this.setState({isToggle:!this.state.isToggle})
                alert('Hello');
            }


            render(){
                return(
                    <div>
                        <button onClick={this.increment}> Increment </button>
                        <button onClick={this.decrement}> Decrement </button>
                        {this.state.counter}
                        <button onClick={this.onEventHandler}> {this.state.isToggle ? 'Hi':'Ajay'} </button>

                    </div>
                    )
            }
        }
        ReactDOM.render(
        <App/>,
        document.getElementById('root'),
      );
    </script>
  </body>
  </html>

0

바인드 명령문을 변경하십시오. => this.delta = this.delta.bind (this);


0
  1. 상태 확인 특정 속성을 만들지 여부를 확인합니다.

this.state = {
            name: "",
            email: ""
            }
            
           
            
this.setState(() => ({ 
             comments: comments          //comments not available in state
             })) 

2. 함수 (예 : handleChange) 내에서 setState를 수행하는 경우 (this)를 확인하십시오. 함수가이 함수에 바인딩되는지 또는 화살표 함수인지를 확인하십시오.

이것을 아래 함수에 바인딩하는 3 가지 방법

//3 ways for binding this to the below function

handleNameChange(e) {  
     this.setState(() => ({ name }))
    }
    
// 1.Bind while callling function
      onChange={this.handleNameChange.bind(this)}
      
      
//2.make it as arrow function
     handleNameChange((e)=> {  
     this.setState(() => ({ name }))
     })
    
//3.Bind in constuctor 

constructor(props) {
        super(props)
        this.state = {
            name: "",
            email: ""
        }
        this.handleNameChange = this.handleNameChange.bind(this)
        }


0

ES5 구문을 사용하는 경우 올바르게 바인딩해야합니다.

this.delta = this.delta.bind(this)

당신이 화살표 기능을 사용할 수 있습니다 ES6하고 이상을 사용하는 경우, 당신은 사용 할 필요가 없습니다 ) (바인드

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