0

While trying to get some data using an async function from S3 I got this error: TypeError: Cannot read properties of undefined (reading 'setState')

What I'm trying to do is to choose a file from pc, upload it to S3 and render it in my dom.

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 great
        try {
            await Storage.put(file.name, file, {
                contentType: "image/png", // contentType is optional
            });
        } catch (error) {
            console.log("Error uploading file: ", error);
        }

        //get from S3, works but not the setState
        try {
            const amen = await Storage.get(file.name, { expires: 60 });
            console.log('amen: ', amen); //correct output data

            //the error is here!
            this.setState({
                uri: amen
            })

            console.log('after: ', this.state.uri); //not output on console

        } catch (error) {
            console.log("Error file: ", error);
        }

    }


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

Everything works correctly, not this:

this.setState({ uri: amen })

Why, what's wrong?

Simon Orro
  • 184
  • 7
  • 20

2 Answers2

1

Ok, I found a solution. Using the arrow function like:

onChange = async (e) => {
    const file = e.target.files[0];

    //upload to S3
    try {
        await Storage.put(file.name, file, {
            contentType: "image/png", // contentType is optional
        });
    } catch (error) {
        console.log("Error uploading file: ", error);
    }

    //get from S3
    try {
        const amen = await Storage.get(file.name, { expires: 60 });

        this.setState({
            uri: amen
        })

    } catch (error) {
        console.log("Error file: ", error);
    }

}
Simon Orro
  • 184
  • 7
  • 20
1

If you declare your function in the following manner

    onChange = (e) => {
             ....rest of your code...
         this.setState({
                uri: amen
            })
    }

It works fine.

If you wish to do it in the other (old, if I am not wrong) way, then you'd need to bind the function to the class for the subcomponent, i.e. the onChange handler in the class to "see" it:

    constructor(props) {
        super(props);
        this.state = { uri: "" };
    }

Lastly, you could do a direct bind inside the return component itself

        return (
                <input type="file" onChange={ this.onChange.bind(this)} />
        );

credit for this issue: https://stackoverflow.com/posts/69687421/edit just made the right matches for you :)

LironShirazi
  • 381
  • 1
  • 8