DEV Community

Run Function after useEffect to Manipulate Data?

mitchelln11 on June 12, 2020

I'm using the OpenWeather REST API which comes in JSON format. I know I have to make my fetch,(Axios in my case) call inside the useEffect because ...
Collapse
 
taylorbeeston profile image
Taylor Beeston

Hi Mitchell, is there any reason why you can't inline

const convertKelvinToFahrenheit = kelvin =>
  (kelvin - 273.15) * 9/5 + 32;

into your LocalWeather component and then simply change axiosGet to

const axiosGet = () => {
        axios.get(`https://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=${process.env.REACT_APP_WEATHER_KEY}`)
        .then(data => setWeather(convertKelvinToFahrenheit(data.data)));
    }
Collapse
 
mitchelln11 profile image
mitchelln11

U talking about just moving the inline function to the LocalWeather component, then just running it like your last block of code?

I just tried that, and I'm getting the following error:
Line 11:8: React Hook useEffect has a missing dependency: 'axiosGet'. Either include it or remove the dependency array react-hooks/exhaustive-deps

Collapse
 
taylorbeeston profile image
Taylor Beeston

I am so sorry, I just realized what you are trying to accomplish. I misunderstood your problem.

As was said before me, you need your KelvinConvert component to return valid JSX in order to be rendered. This can be done by changing its definition to be something like this:

import React from 'react';

const KelvinConvert = ({ kelvin }) => {
  const kToF = k => (k - 273.15) * 9/5 + 32;

  return <li>{kToF(kelvin)}</li>;
};

export default KelvinConvert;

And then passing your Kelvin temperature to it by changing

<KelvinConvert />  // Trying to add converted temperature here

To

<KelvinConvert kelvin={openWeather.kelvin} />

When the useEffect hook finishes, it will update the prop sent to your component.

Please note, I don't actually know what the openWeather object will look like since I haven't used that API, nor do I know specifically what you're trying to get from it, so it is very likely that using openWeather.kelvin like I wrote above will not work. Please replace that with the data you want your KelvinConvert component to convert.

Also, I wrote all of this on my phone, so please forgive any typos or bad code

Thread Thread
 
mitchelln11 profile image
mitchelln11

Sweet, getting 57.938000000000045, so I just need to get that, but that did the trick. Thank you so much.

As far as the object goes with REACT, it's weird, should be openWeather.main.temp, but that comes back undefined. Instead, you have to add it as

openWeather.main && openWeather.main.temp
Thread Thread
 
taylorbeeston profile image
Taylor Beeston

Weird. That's likely because openWeather is an empty object until the API call finishes. You might be able to use the new optional chaining operator to get past that! Try

openWeather?.main?.temp

And see if that works!

As for the float formatting, use the good ol' toFixed method like so

kToF(kelvin).toFixed(2)
Thread Thread
 
mitchelln11 profile image
mitchelln11

57.15, perfect.
I also had no idea about the optional chaining thing. Good to know thanks. That part looks like it's working as well.

openWeather?.main?.temp
AND
openWeather?.weather?.[0].main --- returns cloud/rain/etc.

You know your stuff. It's much appreciated!

Thread Thread
 
anfo000 profile image
anfo000

Wow.. I didnt know about the chaining operator.
Thanks

Thread Thread
 
taylorbeeston profile image
Taylor Beeston • Edited

No problem guys! Happy to help.

About optional chaining, it's extremely new, as in I think it just became official standardized this year, so please make sure you're running any code that uses it through babel (if you used create-react-app it should be doing this already) because browser support is going to be terrible

Collapse
 
muni profile image
Muni Perez

You can do everything in the effect function:

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import {KelvinConvert} from './MathConversions';

const LocalWeather = () => {
    const [openWeather, setWeather] = useState({});

    useEffect(() => {
        axios.get(`https://api.openweathermap.org/data/2.5/weather? 
        q=London,uk&APPID=${process.env.REACT_APP_WEATHER_KEY}`)
        .then(data => {
            setWeather( KelvinConvert(data.data));
         });
    }, []); //  Run once on load

    return (
        <ul id="weather-container">
            <KelvinConvert />  // Trying to add converted temperature here
            <li>{openWeather.main && openWeather.main.temp}&deg;F</li>
            <li>{openWeather.weather && openWeather.weather[0].main}</li>
            <li>{openWeather.name}</li>
        </ul>
    );
}

export default LocalWeather;

If you get this error:

Line 11:8: React Hook useEffect has a missing dependency: 'KelvinConvert'. Either include it or remove the dependency array react-hooks/exhaustive-deps

You can safely ignore it because since your Effect runs only once, you don't need to keep track of the dependency.

Collapse
 
anfo000 profile image
anfo000

Hi Mitchell... The kevin convert is not returning any jsx... That's why you are getting that error..

If you want to convert and show the farenheit maybe return some

{temperature}

.

Also you are not passing any prop to the kelvinconvert component.

Collapse
 
mitchelln11 profile image
mitchelln11

So the following doesn't return anything?

return {temperature};

Also, how do you pass info to the props from 1 component to another after the initial fetch/axios call?