【问题标题】:this.setState is undefinedthis.setState 未定义
【发布时间】:2017-01-05 18:19:20
【问题描述】:

我不断看到使用 => 或 .bind(this) 的答案,但这些解决方案都不起作用。

import React, { Component } from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';

export default class MyWeatherApp extends Component {
  constructor(props) {
  super(props);

  this.state = {};
}

getInitialState() {
  return {
    zip: '',
    forecast: null,
  };
}

_handleTextChange(event) {
  var zip = event.nativeEvent.text;
  this.setState({zip: zip});
}

解决方案:

_handleTextChange = (event) => {
  var zip = event.nativeEvent.text;
  this.setState({zip: zip});
  alert('click');
}

【问题讨论】:

  • 您目前如何尝试绑定this?从您的代码中不清楚。
  • 我们能看到整个代码吗?
  • 首先在 es6 中,反应中没有任何称为 getInitialState() 的东西。你必须这样做 this.state={zip: '', forecast: null}
  • 我正在学习 udemy 课程。 React Native 变化如此之快,以至于课程甚至跟不上语法变化。

标签: reactjs react-native


【解决方案1】:

当您 extend React.Component 使用 ES2015 类语法时,您需要将您的操作处理程序绑定到您的类的上下文。

试试这个:onChange={e => _handleTextChange(e)}

一般来说,最好不要在render 中使用箭头函数或bind 方法,因为它会在任何render 调用中生成函数的新副本。将函数声明移至class constructor

我个人更喜欢在这种情况下使用箭头函数作为类属性

class MyClass extends React.Component {

  handleClick = () => {
    // your logic
  };

  render() {
    return (
      <button onClick={this.handleClick}>Click me</button>
    );
  }
}

它不是 ES2015 规范的一部分,但 babel stage-0 preset 支持这种语法

您可以在this article 中阅读有关 React 中上下文绑定的更多信息

【讨论】:

  • “一般来说,最好不要在渲染中使用箭头函数或绑定方法,因为它会在任何渲染调用时生成函数的新副本。将函数声明移动到类构造函数中。”你在这里是什么意思?所以我onChange={e =&gt; _handleTextChange(e)}的方式不是最好的方式吗?
  • @EmanuelQuimper 如果子组件是纯的,它很可能会对其 props 使用浅相等性检查,以查看它们是否不同,以避免在没有更改的情况下重新渲染。如果您在渲染中创建您的 Lamba 方法,则每次渲染时都会创建一个新的onChange,子组件将看到这个“新”属性并在不需要时重新渲染。
  • @Brandon 感谢您的解释。
  • 我无法导入按钮组件。需要通过 NPM 安装吗?
  • 不,按钮只是一个 html 元素。检查您的 jsx 转译器是否正常工作。哦,我明白了。如果你使用 React Native 它应该是 TouchableElement 而不是
【解决方案2】:

让我详细写一下。因为我不得不浪费很多时间来研究它,我不想让任何人重复这个......

如果你不使用箭头函数,你必须绑定 this 像 Line '9'

class MyClass extends React.Component {

  handleButtonClick(){
    console.log("Hello from here");
  };

  render() {
    return (
      <button onClick={this.handleButtonClick.bind(this)}>Click me</button>
    );
  }
}

另一种方法是使用 ES6 箭头函数。在这种情况下,您不需要绑定“this”。安装 'babel stage-1 preset' 将支持这一点。

在您的项目中运行以下命令:

npm i babel-preset-stage-1 --save

您的 .babelrc 将如下所示。特别是预设中的“stage-1”。

{
  "presets": ["es2015", "react", "stage-1"],
  "env": {
    "development": {
      "plugins": ["react-hot-loader/babel"]
    }
  }
}

正如我所说,您的组件将是这样的:

class MyClass extends React.Component {

      handleButtonClick = () => {
        console.log("Hello from here");
      };

      render() {
        return (
          <button onClick={this.handleButtonClick}>Click me</button>
        );
      }
    }

【讨论】:

  • babel 预设 2 或 3 是否支持?我觉得使用第一阶段预设并不安全,因为新功能仍处于早期阶段。
【解决方案3】:

你也可以像这样在constructor中绑定它

class MyClass extends React.Component {
  constructor(props){
    super(props);
    this.handleButtonClick = this.handleButtonClick.bind(this);
 }
  handleButtonClick(){
    console.log("Hello from here");
  }

  render() {
    return (
      <button onClick={this.handleButtonClick}>Click me</button>
    );
  }
}

【讨论】:

    【解决方案4】:

    问题是:我遇到了 ERROR:this.setState is not a function

    假设我将我的函数绑定到组件构造函数中的状态,如下所示:

     this.getRequestData = this.getRequestData.bind(this);
    

    我的功能是:

    getRequestData(){
        axios.post('http://example.com/getInfo', jsonData)
                            .then(function (res) {
                                console.log(res);
                            })
                            .catch(function (error) {
                                console.log(error);
                            });
                            this.setState({ stateVaribale });
                        })
    }
    

    解决方案是在axios请求中使用arrow functions而不是keywordfunction,导致在axios请求中引用function会让人感到困惑而不是组件状态

    getRequestData(){
    axios.post('http://example.com/getInfo', jsonData)
                            .then(res => {
                            console.log(res);
                            })
                            .catch(error => {
                                console.log(error);
                            });
                            this.setState({ stateVaribale });
                        })}
    

    【讨论】:

      【解决方案5】:

      当您在调用另一个函数的方法中使用胖箭头函数时,也适用于 react-native。 例如 .then((response) => { this.setState({....}) }

      【讨论】:

        【解决方案6】:

        每当您在诸如 axios 请求之类的 api 调用中使用 this 时,在某些情况下您的“this”上下文仍未定义。 在这里详细说明其中的一些-:

        `

        import react from 'React'
        class Test extends from React.Component {
        constructor() {
        super();
        this.state = {
        data: '',
        error: ''
        }
        }
        componentDidMount() {
        url = 'http://abc.go.com';
        axios.get(url).then(function(resposne) {   // Everything fine till now
        this.setState({ data: response });   //Oops this context is undefined
        }
        ).catch(function(err) {
         this.setState({ error: err });       // again this context remains to be undefined
        });
        }
        render() {
        return ( <div>this.state.data</div> ) 
        }
        }`
        

        当你运行上面的代码时,你肯定会得到一个类型错误,比如 正在调用未定义的 setState,类似于此。

        你怎么能解决这个问题? 您可以采用两种方法来解决这种特定类型的问题:

        第一个是您可以在函数内定义一个变量,您将在其中调用 api 并为其分配 'this' 的值,然后您可以从该变量引用您的状态对象。

        import react from 'React'
        class Test extends React.Component
        {
          constructor() { 
             super();
             this.state = {
               data: '',
               error: ''
          };
          componentDidMount() {
           let url = 'http://abc.go.com';
           currentContext = this;   // variable to be assigned this context
           axios.get(url).then(function(resposne) {   // Everything fine till now
           currentContext.setState({ data: response });   //Oops this context is undefined
           }
           ).catch(function(err) {
          currentContext.setState({ error: err });       // again this context remains to be undefined
         });
          }
         render() {
          return ( <div>this.state.data</div> ) 
         }
         }
        

        您可以使用的第二种方法是在 axios 中定义箭头函数,如下所示

        axios.get(url).then((response) => {
          this.setState({ data: response })     //will always be bound to the this context
        }) 
        

        【讨论】:

          【解决方案7】:

          在 react native 中,我们使用 axios 的时候报这个错误,例如

              componentDidMount(){
              axios.get('https://the request url')
              .then( function(response) {
                this.setState({products:response.data.products});
              })
              .catch(function(error) {
                console.log(error);
              })
          }
          

          如果我们这样尝试,我们得到了:

          undefined 不是一个对象(评估 'this.setState')

          那么我们如何解决这个问题,我们可以使用像这样的箭头函数来解决它

          componentDidMount(){
                  axios.get('https://the request url')
                  .then( (response)=> {
                    this.setState({products:response.data.products});
                  })
                  .catch((error)=> {
                    console.log(error);
                  })
              }
          

          这将解决问题,希望这会有所帮助

          【讨论】:

            【解决方案8】:

            您需要绑定您的操作,否则您会在浏览器中看到名为 undefined 的错误 有三种方法可以绑定你的动作

            1. 在render方法中绑定handler this.chngHandler.bind(this)

            例如-

            export class EventBind extends Component{
            constructor(){
                super()
                this.state = {
                    msg:'hello'
                }
            }
            chngHandler(){
                this.setState({
                     msg:'Good bye'
                })
            }
            render(){
                return(
                    <div>
                        {this.state}
                        <button onClick={this.chngHandler.bind(this)}>click</button>
                    </div>
                )
             } }
            
            1. 渲染中的箭头函数方法()=&gt;this.EventHandler()

            例如-

            export class EventBind extends Component{
            constructor(){
                super()
                this.state = {
                    msg:'hello'
                }
            }
            chngHandler(){
                this.setState({
                     msg:'Good bye'
                })
            }
            render(){
                return(
                    <div>
                        {this.state}
                        <button onClick={()=>this.chngHandler()}>click</button>
                    </div>
                )
            }}`
            

            3.在构造函数中绑定事件处理器 this.EventHandler = this.EventHandler.bind(this) 例如-:

            export class EventBind extends Component{
            constructor(){
                super()
                this.state = {
                    msg:'hello'
                }
                this.chngHandler = this.chngHandler.bind(this)
            }
            chngHandler(){
                this.setState({
                     msg:'Good bye'
                })
            }
            render(){
                return(
                    <div>
                        {this.state}
                        <button onClick={this.chngHandler}>click me </button>
                    </div>
                )
            }}
            

            因为绑定在构造函数中发生一次,这比在渲染方法中的绑定要好

            第三种方法也可以这样-:

            export class EventBind extends Component{
            constructor(){
                super()
                this.state = {
                    msg:'hello'
                }
                this.chngHandler = this.chngHandler.bind(this)
            }
            // chngHandler(){
            //     this.setState({
            //          msg:'Good bye'
            //     })
            // }
            chngHandler = ()=>{
                this.setState({
                    msg:'Good Bye'
                })
            }
            render(){
                return(
                    <div>
                        {this.state}
                        <button onClick={this.chngHandler}>click me </button>
                    </div>
                )
            }}
            

            【讨论】:

            • 谢谢您我尝试了您在此共享的所有选项,但仍然出现相同的错误。 setState 未定义。
            猜你喜欢
            • 1970-01-01
            • 2018-04-03
            • 1970-01-01
            • 2018-10-24
            • 2019-12-04
            • 1970-01-01
            • 1970-01-01
            • 2019-11-16
            • 1970-01-01
            相关资源
            最近更新 更多