suprita shankar
suprita shankar

Reputation: 1589

State does not change in my reducer when action is dispatched

I am not able to retrieve the state in the reducer

MyComponent looks like this

const MyComponent = ({name, features, onClick}) => {
  return (
        <div>
            Hello! {name}
            <Button onClick={() => { onClick(features); }}> Weight</Button>
        </div>
    );

const mapDispatchToProps = (dispatch: any) => {
  return {
    onClick: (features) => {
        dispatch(weightSort(features));
    }
  };
};
const mapStateToProps = (state: any, ownProps: any) => {
  console.log(state); //Displays the state
  return {
    name: "John Doe",
    features: ownProps.features,
  };
};

export const FeatureBlock = connect(mapStateToProps, mapDispatchToProps)(MyComponent);

My actions and reducers looks like below:

// Action Creator
export const  weightSort = (features) => {
console.log("inside the weight sort action creator!!!");
  return {
    type: "SET_WEIGHT_FILTER",
    filter: "DESC",
    features,
  };
};

// Reducer
export const weightFilter = (state = [], action) => {
  switch (action.type) {
    case "SET_WEIGHT_FILTER":
        console.log(state); // Gives me empty state
        console.log("++inside weight filter+++++", action); //Displays action
        return state;
    default:
        return state;
  }
};


export const FeatureBlock = connect(
  mapStateToProps,
  mapDispatchToProps,
)(MyComponent);

What am I missing here? Any help will be appreciated!

Upvotes: 1

Views: 785

Answers (1)

Yo Wakita
Yo Wakita

Reputation: 5460

In your reducer, when you console.log(state), it is correct in returning an empty array because you haven't done anything to modify it.

// Reducer
   export const weightFilter = (state = [1,2,3], action) => {
     switch (action.type) {
       case "SET_WEIGHT_FILTER":
           console.log(state); // This will show [1,2,3] because [1,2,3] is the initial state.
           console.log("++inside weight filter+++++", action); //Displays action
           return state;
       default:
           return state;
     }
   };

My guess is that you want something like this for your reducer:

// Action Creator
export const  weightSort = (name, features) => {
console.log("inside the weight sort action creator!!!");
  return {
    type: "SET_WEIGHT_FILTER",
    name,
    features,
  };
};
// Reducer
  export const weightFilter = (
    state = {
      name: '',
      features: [],
    },
    action
  ) => {
     switch (action.type) {
       case "SET_WEIGHT_FILTER":
           return {...state, name: action.name, features: action.features}
       default:
           return state;
     }
   };

and then in your mapStateToProps you would map out the attributes like so:

const mapStateToProps = (state: any, ownProps: any) => {
  console.log(state); //Displays the state
  return {
    name: state.weightFilter.name,
    features: state.weightFilter.features,
  };
};

and your button would have a name prop passed into the function like so:

<Button onClick={() => { onClick(name, features); }}> Weight</Button>

If you would like to sort your data, you can do so either in the reducer or inside the container. I prefer to do it in the container and like to use the lodash sortBy function. It works like this:

import { sortBy } from 'lodash' //be sure to npm install lodash if you use this utility
...
...
function mapStateToProps(state) {
  return {
    name: state.weightFilter.name,
    features: sortBy(features, ['nameOfPropertyToSortBy'])
  };
}

Here is the lodash documentation on sortBy: https://lodash.com/docs/4.17.4#sortBy

Hope that helps!

Upvotes: 3

Related Questions