You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React组件调用setState报错:TypeError: Cannot read properties of undefined (reading 'setState')(S3文件上传渲染场景)

TypeError: Cannot read properties of undefined (reading 'setState') in React async function with S3

Problem Description

I'm trying to upload a local file to S3, then fetch it back and render it in the DOM using a React class component. Everything works except the this.setState call after retrieving the file URL from S3 — I get the error TypeError: Cannot read properties of undefined (reading 'setState'). Here's my component code:

class Dashboard extends React.Component {
  constructor(props) {
    super(props);
    this.state = { uri: "" };
  }

  async onChange(e) {
    const file = e.target.files[0];
    // Upload to S3 - works fine
    try {
      await Storage.put(file.name, file, {
        contentType: "image/png", // contentType is optional
      });
    } catch (error) {
      console.log("Error uploading file: ", error);
    }
    // Get from S3 - returns correct data, but setState fails
    try {
      const amen = await Storage.get(file.name, { expires: 60 });
      console.log('amen: ', amen); // Correct URL is logged
      // This line throws the error!
      this.setState({ uri: amen })
      console.log('after: ', this.state.uri); // Doesn't log because of the error
    } catch (error) {
      console.log("Error file: ", error);
    }
  }

  render() {
    return (
      <div>
        <input type="file" onChange={this.onChange} />
        <img src={this.state.uri}/>
      </div>
    )
  }
}

Root Cause

The issue is incorrect this binding in your onChange method. When you pass this.onChange as the event handler to the <input> element, the method loses its context (the component instance) when it's invoked by the browser's event system. So inside the async onChange function, this is undefined, which is why trying to call this.setState throws an error.

Solutions

You can fix this in one of three common ways:

1. Bind this in the constructor

Add this line to your constructor to explicitly bind the component instance to the onChange method:

constructor(props) {
  super(props);
  this.state = { uri: "" };
  // Bind the method here
  this.onChange = this.onChange.bind(this);
}

2. Use an arrow function in the event handler

Wrap the onChange call in an arrow function when passing it to the input. Arrow functions preserve the surrounding context (this will refer to the component instance):

<input type="file" onChange={(e) => this.onChange(e)} />

3. Define onChange as an arrow function class field

If your project supports class fields (enabled by default in Create React App), define the method directly as an arrow function. This automatically binds this to the component instance:

class Dashboard extends React.Component {
  constructor(props) {
    super(props);
    this.state = { uri: "" };
  }

  // Use arrow function for the method
  onChange = async (e) => {
    // Your existing code here...
  }

  // Rest of the component...
}

Bonus Note

Keep in mind that setState is asynchronous. The console.log('after: ', this.state.uri) line right after setState won't show the updated value immediately. To log the updated state, use the setState callback:

this.setState({ uri: amen }, () => {
  console.log('after: ', this.state.uri); // Will log the updated URI
});

内容的提问来源于stack exchange,提问作者Simon Orro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 11:02:38