PotatoBox
PotatoBox

Reputation: 608

ReactJS: Redux state is not changing

I'm just starting with React and Redux and stumbled upon something I can't figure out by myself - I think that Redux state is not changing and it's causing (some of) errors. I'm checking state with use of [email protected]. My code:

Categories.js:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { getCategories } from '../../actions/categories';

export class Categories extends Component {
    static propTypes  = {
        categories: PropTypes.array.isRequired
    };

    componentDidMount() {
        this.props.getCategories();
    }

    render() {
        return (
            <div>
                Placeholder for categories.
            </div>
        )
    }
}

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

export default connect(mapStateToProps, { getCategories })(Categories);

../../actions/categories.js:

import axios from "axios";

import { CATEGORIES_GET } from "./types";

export const getCategories = () => dispatch => {
  return axios
    .get("/api/notes/categories/")
    .then(res => {
      dispatch({
        type: CATEGORIES_GET,
        payload: res.data
      });
    })
    .catch(err => console.log(err));
};

reducers/categories.js:

import { CATEGORIES_GET } from '../actions/types.js';

const initialState = {
    categories: []
};

export default function (state = initialState, action) {
    switch (action.type) {
        case CATEGORIES_GET:
            return {
                ...state,
                categories: action.payload
            };
        default:
            return state;
    }
}

store.js:

import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'remote-redux-devtools';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const initialState = {};
const middleware = [thunk];

const store = createStore(
    rootReducer,
    initialState,
    composeWithDevTools(applyMiddleware(...middleware)));

export default store;

reducers/index.js

import { combineReducers } from "redux";
import categories from './categories';

export default combineReducers({
    categories,

});

Using remote-redux-devtools, I've never seen anything in my state. Currently this code above gives me 3 errors, two of them being

this.props.getCategories is not a function

My guess is that because there is some issue with Categories class, it's not passing anything to state and it could be root cause of errors. I had one more error, connected to Categories not being called with attributes, but for debug purposes I put empty array there - one error dissapeared, but that's it. I've also tried adding constructor to Categories and called super(), but did not help also.

Upvotes: 0

Views: 84

Answers (3)

herodrigues
herodrigues

Reputation: 967

Your props don't have getCategories method, because you didn't pass it as a function to connect.

A better approach is to define only the action code in your actions file and then use mapDispatchToProps.

../../actions/categories.js

import axios from "axios";

export const getCategories = () => {
  axios
    .get("/api/notes/categories/")
    .then(res => res.data);
    })
    .catch(err => console.log(err));
};

Categories.js

import { getCategories } from '../../actions/categories'
import { CATEGORIES_GET } from "./types";

const mapDispatchToProps = dispatch => {
  return {
     getCategories: () => dispatch(() => { type: CATEGORIES_GET, payload: getCategories() }),
  }
}

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

Upvotes: 0

tomrlh
tomrlh

Reputation: 1066

When you're mapping the state in a component, you must access the desired variable through a reducer.

So instead of:

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

You must use:

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

Upvotes: 0

Gregory Friedman
Gregory Friedman

Reputation: 76

I believe your issue is that you're exporting your Categories class twice, once connected, the other not.

If you remove export from export class Categories extends Component, does it work as expected?

Upvotes: 2

Related Questions