Ad

Redux MapDispatchToProps Not Functioning

- 1 answer

So I'm new to Redux and I'm trying to get this base model working so I can quickly work on a small personal project, I set everything up and have no errors but I'm trying to test and my function doesn't work so I was hoping someone could point out what I've missed.

I've followed multiple different tutorials and each has a different approach so that has me lost a bit so I apologize for that.

My store.js looks like so

import rootReducer from "./reducers";
import thunk from "redux-thunk";
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store;

I've used a combineReducers in my index.js in reducers folder and the auth: points to the authReducer.js file, which is this


const INIT_STATE = {
  email: "",
  password: "",
  isLoggedIn: "false"
};

export default (state = INIT_STATE, action) => {
  switch (action.type) {
    case IS_LOGGED_IN_CHANGE:
      console.log(action);
      return {
        isLoggedIn: action.value
      };
    default:
      return state;
  }
};

Now What I'm aiming for is to have a button that changes that "IsLoggedIn" initial state to a true string instead of a false, I've went into my actions folder and made an authActions.js which looks like so

import { IS_LOGGED_IN_CHANGE } from "../actions/types";
import store from "../store";

export const isLoggedInChange = value => {
  return dispatch => {
    dispatch({
      type: IS_LOGGED_IN_CHANGE,
      value
    });
  };
};

And Finally I want to show you my component page which is showing all this, It's looking like so

import { connect } from "react-redux";

import styles from "./Landing.module.css";
import { isLoggedInChange } from "../../actions/authActions";

class Landing extends Component {
  makeTrue = () => {
    isLoggedInChange("true");
  };

  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: ""
    };
  }
  render() {
    return (
      <div className={styles.background}>
        <button onClick={this.makeTrue}>MAKE TRUE</button>
        {this.props.isLoggedIn}
      </div>
    );
  }
}

const mapStateToProps = state => ({
  isLoggedIn: state.auth.isLoggedIn
});

const mapDispatchToProps = dispatch => ({
  isLoggedInChange: value => dispatch(isLoggedInChange(value))
});

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

Can you tell if I dropped anything making this? why is the button not changing the store state? TIA

Ad

Answer

Two problems here. You're calling your action creator directly not props.isLoggedInChange

  makeTrue = () => {
    this.props.isLoggedInChange("true");
  };

And you need to spread the old state inside your action

case IS_LOGGED_IN_CHANGE:
  console.log(action);
  return {
    ...state,
    isLoggedIn: action.value
  };

Isn't the point of my mapDispatchToProps to be able to use the function right away as I was doing

Yes, the problem is mapDispatchToProps inject a function (or multiple functions) wrapped in dispatch into your props.

import { actionCreator } from './actions

const mapDispatchToProps = dispatch =>({
    actionCreator : () => dispatch(actionCreator)
})  

Now you have two actionCreator, one globally available in the scope (which is your action creator) and props.actionCreator which is the original action creator wrapped in dispatch. So when you call actionCreator() from inside your component it won't throw any errors (cause there is a function named actionCreator in the scope, but you will be calling the wrong function, the right one is located at props.actionCreator.

Why do I need to spread the state?

A reducer is a pure function which receives a state and action and returns the new state. When you just return

return {
    isLoggedIn : true
}

You're actually overwriting the original state (which contains other properties), so first you need to spread the original state to maintain it's structural integrity and them overwrite the properties you want

return{
   ...state,
   isLoggedIn : !state.isLoggedIn
}
Ad
source: stackoverflow.com
Ad