【问题标题】:getting error: Cannot read property state of undefined出现错误:无法读取未定义的属性状态
【发布时间】:2018-04-12 03:04:46
【问题描述】:
import React, { Component } from "react";
import FormUpdate from "../components/formUpdate";
import { fetchClothingItem, updateClothingItem } from "../actions/crud";

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

        this.state = {
          updateClothingItem: {}
        };
    }

    componentWillMount() {
        fetchClothingItem(this.props.match.params.postId)
        .then(data => {
        this.setState(state => {
          state.updateClothingItem = data;
          return state;
        });
        console.log("data", data);

        //HERE IT IS RETURNING EXPECTED DATA       

        console.log("this.state.updateClothingItem",this.state.updateClothingItem)    
          })
        .catch(err => {
            console.error("err", err);
        });
    }

    handleSubmit(data) {

        //HERE IT IS THROWING: 

        > "TypeError: Cannot read property 'state' of undefined"

        console.log("this.state.updateClothingItem", this.state.updateClothingItem);
            updateClothingItem(this.state.updateClothingItem.id, data); this.props.router.push("/update");
    }
    render() {
        return (
        <div>
        <FormUpdate
          //onSubmit={this.handleSubmit.bind(this)}
          id={this.state.updateClothingItem.id}
          name={this.state.updateClothingItem.name}
          sleeveLength={this.state.updateClothingItem.sleeveLength}
          fabricWeight={this.state.updateClothingItem.fabricWeight}
          mood={this.state.updateClothingItem.body}
          color={this.state.updateClothingItem.color}
        />
        <button
          type="submit"
          onClick={this.handleSubmit}
          className="addItemButton"
        >
        Button
        </button>
      </div>
    );
  }
}

【问题讨论】:

    标签: reactjs undefined state typeerror


    【解决方案1】:

    构造函数中还没有状态

    如果你想在构造函数中设置状态,你可以这样做

    class SomeComponent extends Component {
       constructor(props){
          super(props)
    
          this.state = { someKey: someValue }
       }
    }
    

    甚至像这样

    class SomeComponent extends Component {
    
       state = { someKey: someValue }
    
    }
    

    但在这种情况下,babel 应该正确配置

    【讨论】:

    • 这两者有什么区别?我遇到了第一个例子的问题。
    • @Jesse 刚刚更新了我的答案 - ... 意味着应该有一些值
    【解决方案2】:

    在 React 代码实现方面存在一些技术上的错误。

    首先, 使用 ES6 编写类的风格,任何需要访问 Class 属性的函数都需要显式地binded。在您的情况下,您需要使用arrow function of 或binding in constructor 绑定handleSubmit 函数。

    更多详情请查看此答案:Why and when do we need to bind functions and eventHandlers in React?

    其次:您在 componentWillMount 函数中设置了异步请求,并且在它的成功响应中,您正在设置状态。但是在渲染组件后会触发在componentWillMount 中使用setState,因此您仍然需要进行未定义的检查。您应该使用 componentDidMount 生命周期函数来处理异步请求。

    检查这个答案是否有AJAX request in componentDidMount or componentWillMount

    第三: setState 是异步的,因此在 setState 函数之后记录状态值不会导致显示正确的输出。请改用setState callback

    查看这些答案了解更多详情:

    calling setState doesn't mutate state immediately

    When to use React setState callback

    代码:

    export default class Update extends Component {
        constructor(props) {
            super(props);
    
            this.state = {
              updateClothingItem: {}
            };
        }
    
        componentDidMount() {
            fetchClothingItem(this.props.match.params.postId)
            .then(data => {
            this.setState(state => {
              state.updateClothingItem = data;
              return state;
            });
            console.log("data", data);
    
            //HERE IT IS RETURNING EXPECTED DATA       
    
            console.log("this.state.updateClothingItem",this.state.updateClothingItem)    
              }) // this statement will not show you correct result since setState is async 
            .catch(err => {
                console.error("err", err);
            });
        }
    
        handleSubmit = (data) =>  { .    // binding using arrow function here
    
            console.log("this.state.updateClothingItem", this.state.updateClothingItem);
                updateClothingItem(this.state.updateClothingItem.id, data); this.props.router.push("/update");
        }
        render() {
            return (
            <div>
            <FormUpdate
              //onSubmit={this.handleSubmit.bind(this)}
              id={this.state.updateClothingItem.id}
              name={this.state.updateClothingItem.name}
              sleeveLength={this.state.updateClothingItem.sleeveLength}
              fabricWeight={this.state.updateClothingItem.fabricWeight}
              mood={this.state.updateClothingItem.body}
              color={this.state.updateClothingItem.color}
            />
            <button
              type="submit"
              onClick={this.handleSubmit}
              className="addItemButton"
            >
            Button
            </button>
          </div>
        );
      }
    }
    

    【讨论】:

    • 这个绑定的东西每次我使用函数访问状态数据时都让我发疯,这在语法上来自传统语言和 UI 框架背景,真是太奇怪了
    【解决方案3】:

    您忘记将 handleSubmit 函数绑定到该类。您可以使用箭头函数来定义函数。

    handleSubmit=(data) =>{
    ...
    }
    

    或者你可以在你的构造函数中绑定函数。

    constructor(props) {
            super(props);
            this.state = {
              updateClothingItem: {}
            };
            this.handleSubmit= this.handleSubmit.bind(this,data);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-08
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      • 2020-05-16
      • 2019-06-08
      • 2021-12-10
      相关资源
      最近更新 更多