Search code examples
javascriptreduxaxiosopenweathermap

How to fetch data in weather API on Redux with parameters?


My question is simple as how can I get city and country, on axios fetch with multiple parameters on URL with Redux?

In the ROOT_URL the parameters are city and country change:

const URL = `http://api.openweathermap.org/data/2.5/weather?q=${city},${country}&appid=${API_KEY}&units=metric`;

My actions

import axios from 'axios';
const API_KEY = "a3de5cffde10c377d199699b3da6fc6f";

export function getWeather (city, country) { 
    const URL = `http://api.openweathermap.org/data/2.5/weather?q=${city},${country}&appid=${API_KEY}&units=metric`;
    
    return(dispatch)=>{
        return axios.get(URL)
        .then(res => {
            dispatch(changeWeather(res));
        }).catch(err =>{
            console.log('error', err);
        });
      
    }
}
const changeWeather = weather => ({
    type: 'CHANGE_WEATHER',
    weather
});

The reducers

const weatherDefaultState = {
    city:undefined, 
    country:undefined, 
    
};
export default (state=weatherDefaultState,action)=>{
    switch(action.type) { 
        case 'CHANGE_WEATHER':
        return {...state, weather: action.weather}
        default: return state;
    }
};

and the component with redux, runs but the button does not perform any action, what is the error?

import React from 'react';
import {connect} from 'react-redux';
import { getWeather } from '../actions/weather';
class Weather extends React.Component {
    
    loadWeather = () => { 
        const API_KEY = 'a3de5cffde10c377d199699b3da6fc6f';
        const URL = `http://api.openweathermap.org/data/2.5/weather?q=Merida,mx&appid=${API_KEY}&units=metric`;
        
        return(dispatch)=>{
            return axios.get(URL)
            .then(res => {
                dispatch(getWeather(res));
            }).catch(err =>{
                console.log('error', err);
            });
          
        }
    }
    render() {
        return(<div>
            <WeatherForm
                 weather={this.props.weather}
                 handleClick={this.loadWeather}
            />
            </div>
        )
    }
}

class WeatherForm extends React.Component {
    render() {
        return(<div>
            <button
            className='boton-color'
            style={{backgroundColor:'darkcyan'}}
            onClick={()=>{this.props.handleClick() }} 
            type="button" >
            <p 
            className="card-text-correo"> 
            clima </p></button>
            </div>)
    }
}
const mapStateToProps = (state) => {
    return state
};
export default connect(mapStateToProps)(Weather);

Solution

  • According to your code, you don't make HTTP call at all. Inside your loadWeather function, which is just method on the component, you return a function which takes dispatch as an argument, this isn't correct. You have your async action, which is great ( I assume you have installed and connected redux-thunk properly.

    So, you need to get access to this action inside your component. This should be made using connect module which you installed and connected. But it also takes another parameter to connect actions to props.

    const mapStateToProps = (state) => {
        return state
    };
    
    /* This one you should add */
    const mapDispatchToProps = dispatch => {
       return {
          getWeatherDispatch: (city, country) => {
              dispatch(getWeather(city, country))
          }
       }
    };
    export default connect(mapStateToProps, mapDispatchToProps)(Weather);
    

    As a result, you can invoke your action inside a component using this.props.getWeatherDispatch(yourCity, yourCountry)