0

I have 5 cities and their weather displayed on a card when you click one I want more details to appear on another card. I also want the detailed card to have initial data of the first city. Problem is when I try to set the clicked data to state in useEffect the state goes empty, even the initial data. If I add the dependency array [props.activeWeather] in useEffect I can click and it will show the data but the initial data won't show as the state shows empty. I'm using props to send the card the clicked city object as well as the first array of data.

const ActiveWeather = (props) => {
    const [weather, setWeather] = useState(props.data);

//adding this cause the weather state to go empty?
    useEffect(() => {
        if (props.activeWeather) {
            setWeather(props.activeWeather);
        }
    }, []);

    console.log(weather);
    return (
        <Container>
            <Card>
                <Card.Header> {weather?.city}</Card.Header>
                {weather?.temp}
            </Card>
        </Container>
    );
};

export default ActiveWeather;

Parent Component

const fetchCity = async (city) => {
    const res = await axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}`);

    return {
        description: res.data.weather[0].description,
        icon: res.data.weather[0].icon,
        temp: res.data.main.temp,
        city: res.data.name,
        country: res.data.sys.country,
        id: res.data.id,
    };
};

function App() {
    const [data, setData] = useState([]);

    const [activeWeather, setActiveWeather] = useState([]);

    useEffect(() => {
        const fetchCities = async () => {
            const citiesData = await Promise.all(["Ottawa", "Toronto", "Vancouver", "California", "London"].map(fetchCity)).catch((err) => {
                console.log("error:", err);
            });

            setData((prevState) => prevState.concat(citiesData));
        };

        fetchCities();
    }, []);

    const handleClick = (event) => {
        const weather = JSON.parse(event.target.dataset.value);
        setActiveWeather(weather);
    };

    return (
        <div className="App">
            <Header />
            <Container>
                <Row>
                    <Col>
                        <WeatherPanel data={data} handleClick={handleClick} />
                    </Col>
                    <Col>{data.length > 0 && <ActiveWeather activeWeather={activeWeather} data={data[0]} />}</Col>
                </Row>
            </Container>
        </div>
    );
}

export default App;

when trying to use useEffect...

data

zer0day
  • 236
  • 1
  • 3
  • 11
  • Do you even need the useEffect? Since `activeWeather` is tied to the state in your parent, any change to it is going to result in a re-render anyways – WebbH Jul 02 '21 at 03:28

2 Answers2

0
 if (props.activeWeather) {
        setWeather(props.activeWeather);
    }

is always exectued because an empty array is truthy. So when activeWeather is an empty array, weather is being set to []

WebbH
  • 2,379
  • 1
  • 15
  • 26
0

Try like this :-

   ​useEffect(() => {
    ​if (props.activeWeather) {
       ​setWeather(props.activeWeather);
   ​}}, [props.activeWeather])

Set your props activeWeather in useEffect array. if any changes done in your parent component chiled useEffect automatically tigger.

Mariselvam
  • 149
  • 4