-1

I'm learning react by building a weather api. I make an API call and store it in state.

  state = {
        forecasts: {
            error: null,
            isLoaded: false,
            forecasts: []
        }
    }

    componentDidMount() {
        const endpoint = `http://dataservice.accuweather.com/forecasts/v1/daily/5day/207931?apikey=KEY&language=en&details=true&metric=true`;
        fetch(endpoint)
        .then(res => res.json())
        .then((result) => {
            this.setState({
                'forecasts.isLoaded': true,
                'forecasts.forecasts': result.DailyForecasts,
            });
        },
        (error) => {
            this.setState({
                'forecasts.isLoaded': true,
                'forecasts.error': error
            });
        })
    }

When I pass this down as props, I get no data?

<WeatherOverview weather={this.state.forecasts}/>
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
  • please provide the code where you pass it down as props – Dani Jul 04 '20 at 15:04
  • @Dani - I've edited the post. –  Jul 04 '20 at 15:05
  • 1
    Does this answer your question? [How to update nested state properties in React](https://stackoverflow.com/questions/43040721/how-to-update-nested-state-properties-in-react) – Emile Bergeron Jul 04 '20 at 15:35
  • If your state only has the `forecasts` object in it, you could just remove the nesting and then only update the values you'd like and let React deal with the shallow merge. `this.setState({ isLoaded: true, error });` which would result in this state: `{ error, isLoaded: true, forecasts: [] }` – Emile Bergeron Jul 04 '20 at 15:50

2 Answers2

2

Use spread syntax to copy the entire previous object and then override some of its keys. You should also use the form of setState that takes a function because you want to reference the previous value of state.forecasts:

.then((result) => {
            this.setState(state => ({
                forecasts: {
                    ...state.forecasts,
                    isLoaded: true,
                    forecasts: result.DailyForecasts,
                },
            }));
        },
        (error) => {
            this.setState(state => ({
                forecasts: {
                    ...state.forecasts,
                    isLoaded: true,
                    error: error,
                },
            }));
        })

or you may want entirely new objects to wipe out the previous error state:

.then((result) => {
            this.setState({
                forecasts: {
                    error: null,
                    isLoaded: true,
                    forecasts: result.DailyForecasts,
                },
            });
        },
        (error) => {
            this.setState(state => ({
                forecasts: {
                    forecasts: [],
                    isLoaded: true,
                    error: error,
                },
            }));
        })
Ross Allen
  • 43,772
  • 14
  • 97
  • 95
  • Spreading gives me the following error 'state is not defined' –  Jul 04 '20 at 15:35
  • 1
    @johnst123v notice that Ross is passing an arrow function to `setState` which defines a local param `state`. This is how you should be setting a nested state value. – Emile Bergeron Jul 04 '20 at 15:36
-2

you are not passing the state correctly, you need to pass the state without quotation marks

this.setState({
 'forecasts.isLoaded': true,
 'forecasts.forecasts': result.DailyForecasts,
});

should be like this:

    this.setState({
     forecasts: {
      ...state.forecasts,
      isLoaded:true,
      forecasts:result.DailyForecasts},
   });
Rodolfo Campos
  • 199
  • 1
  • 8
  • I get the following error then - Parsing error: Unexpected token, expected "," –  Jul 04 '20 at 15:11
  • @johnst123v it replaces the `forecasts` object with an new object that's missing some properties, so it's unintentionally losing some state data at the same time. – Emile Bergeron Jul 04 '20 at 15:34
  • 1
    @EmileBergeron yeah you're right i should include the spread operator, my bad – Rodolfo Campos Jul 04 '20 at 15:47