How can I set state in a function that is in a utility file?

38
February 23, 2021, at 10:30 AM

I had a function in a react class that I was using to pull data.

It was working great, but I then found out I needed to use the same function in a few other places.

So I decided to put the function in it's own file so I could re-use it.

So here it is:

import axios from 'axios';
export const  getGalaxyName = async (id) => {
    try {
        const { data: response } = await axios.get(`/api/scienceClass/galaxy/${id}`)
        this.setState({ galaxyName: response.name });
    }
    catch (error) {
        console.log(error);
    }
}

And then in a component, I use it like this:

import { getGalaxyName } from './ScienceClassUtils';
    render() {
        getGalaxyName(slide.z_GalaxyId);
    
    

But now I am getting this error:

ScienceClassUtils.js:35 TypeError: Cannot read property 'setState' of undefined

I am guessing it's because I'm trying to still set the state in the function like I did when it was originally inside the react class.

So how can I still use it now that it's separated out in another file, but still have this.setState({ galaxyName: response.name }); ?

Thanks!

Answer 1

Easiest way from here to there might be to have it return the promise instead of calling setState directly:

const { data } = await axios.get(`/api/scienceClass/galaxy/${id}`)
return data.name;

Then your component or anyone else could do whatever they need to do with it:

getGalaxyName(id).then(galaxyName => this.setState({ galaxyName });
Answer 2

The bottom line is you can't set the state outside a React component. Make your utility function return the data you need and set the state from within your react component.

Refactor your util function to look like this

import axios from 'axios';
export const  getGalaxyName = async (id) => {
    try {
        const { data: response } = await axios.get(`/api/scienceClass/galaxy/${id}`)
        return { galaxyName: response.name }
    } catch (error) {
        console.log(error);
    }
}

From within your component call the method in a componentDidMount. lifecycle hook like this

class SampleComponent extends React.component {
  
  // Add this lifecycle hook
  componentDidMount() {
    getGalaxyName(slide.z_GalaxyId).then((data) => {
      this.setState(data)
    });
  }

  render() {
    // use state data as needed here
  }
}
Answer 3

There are at least two possible approaches:

  1. Create a helper method for setting the galaxyName and then pass it to axios utility, and it will call it and pass the response.name to it.
  2. Return the response from axios utility and use Promise methods .then, .catch, .finally, to handle the success, fail, finished cases as needed. Note that, the data you return from the axios utility will be passed to these methods as parameter.
READ ALSO
laravel irazasyed/telegram-bot-sdk

laravel irazasyed/telegram-bot-sdk

this is my code which is send photo

20
How to get data from DOM to Swift

How to get data from DOM to Swift

I am trying to export some data from an web-page and use it in the swift program by means of webkit

16
Retrofit 2: App Crashes When Reading JSON Without Internet

Retrofit 2: App Crashes When Reading JSON Without Internet

I am trying to stop my app from crashing when trying to read json information using Gson and Retrofit2 when user has no internet connectionAny Ideas?

23
php mysql search for text

php mysql search for text

I am writing a blog, and i have to post things in series, and i need to link them togetherI want to input the next post id to the previous post

47