0
votes

I am firing an action to do some toggle functionality, however, my react component is not re rendering even though the redux state is

const Countries = ({ countries, toggleCountry }) => (
  <div>
    <h4> All Countries </h4>
    <div className="container">
      {countries.map((country, index) => (
        <div
          key={index}
          className={`countryContainer ${country.visited ? 'visited' : ''}`}
        >
          <img src={country.flag} alt="countryFlag" />
          <p className="countryName"> {country.name} </p>
          <button onClick={() => toggleCountry(country.name)}>
            {country.visited ? 'undo' : 'visited'}
          </button>
        </div>
      ))}
    </div>
  </div>
);

const mapStateToProps = ({ countries }) => ({
  countries
});

const mapDispatchToProps = dispatch =>
  bindActionCreators(
    {
      toggleCountry
    },
    dispatch
  );

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Countries);

when I click this button it is correctly toggling in the redux state but the component does not re render to show the new button label or change the class name

this is my reducer:

const initialState = []

export default(state = initialState, action) => {
  switch(action.type){
    case 'UPDATE_INITIAL_COUNTRIES':
      return state.concat(action.countries)
    case 'UPDATE_COUNTRY_VISITED':
      return state.map(country => (
        country.name === action.name ? {...country, visited: !country.visited} : country
      ))
    default:
      return state;
  }
}

and my action creator

export const toggleCountry = countryName => {
  return dispatch => {
    dispatch({ type: 'UPDATE_COUNTRY_VISITED', countryName })
  }
}
2
Can you show your toggleCountry action creator code? - Cuong Vu
@VuHuuCuong done - Red Baron
And the corresponding reducer too :) - Cuong Vu
@VuHuuCuong also done - Red Baron
flips sake, fixed it. was using name instead of ` countryName` facepalm - Red Baron

2 Answers

2
votes

The action expects action.name, but instead receives action.countryName

The problem is here

export const toggleCountry = countryName => {
  return dispatch => {
    dispatch({ type: 'UPDATE_COUNTRY_VISITED', countryName })
  }
}

fix:

export const toggleCountry = name => {
  return dispatch => {
    dispatch({ type: 'UPDATE_COUNTRY_VISITED', name })
  }
}
0
votes

Here country.name === action.name ? {...country, visited: !country.visited} : country you are searching for action.name but in below declaration you have not given payload a proper name

export const toggleCountry = countryName => {
      return dispatch => {
        dispatch({ type: 'UPDATE_COUNTRY_VISITED', countryName })
      }
    }

Fix:

export const toggleCountry = countryName => {
      return dispatch => {
        dispatch({ type: 'UPDATE_COUNTRY_VISITED', name :countryName })
      }
    }