出现错误:无法读取未定义的属性状态

Posted

技术标签:

【中文标题】出现错误:无法读取未定义的属性状态【英文标题】: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>
    );
  

【问题讨论】:

【参考方案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);
    

【讨论】:

以上是关于出现错误:无法读取未定义的属性状态的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS TypeError:无法读取未定义的属性“setState”[重复]

由于无法读取未定义角度的属性“键”而出现错误

下一个 redux 包装器出现无法读取未定义的属性 'getState' 的错误

useContext 和 useReducer Hooks 不起作用。错误:无法读取未定义的属性“状态”

TypeError:使用状态时无法读取未定义的属性“0”

无法使用 Ngrx 读取未定义的属性“firebaseApp”