0

I have an issue with my redux. This is the first time I am using it in React. I have managed to successfully use it for logging and registering users. However, I have an array of objects created on backend which I am fetching with axios. Axios logs the data and my action creator also logs data in payload. However, it does not update my new state. I have no idea what I'm doing wrong as I tried it exactly the same way as with my login and register states, however these were only boolean values. I have googled and searched for a solution. I tried mapping new array, Object.assign and many others but I can't seem to get it working. Is there any special way on creating new array in state? or can I just assign it action.payload? I appreciate all help

// store.js

import { applyMiddleware, createStore } from 'redux';
import logger from 'redux-logger';
import thunk from 'redux-thunk';

import reducer from './reducers/reducer';

const middleware = applyMiddleware(logger, thunk);

export default createStore(reducer, middleware);

// rootReducer.js

import { combineReducers } from 'redux';

import registerReducer from './registerReducer';
import loginReducer from './loginReducer';
import productsReducer from './products';

export default combineReducers({
  registerReducer,
  loginReducer,
  productsReducer
});

// productsReducer // I believe sth must be wrong here

import { SHOW_PRODUCTS, SELECT_PRODUCT } from '../actions/products';

const initialState = {
  productsList: []
};

const productsReducer = (state = initialState, action) => {
  switch (action.type) {
    case SHOW_PRODUCTS: 
      return {...state, productsList: action.payload}
  }
  return state;
}

export default productsReducer;

// actions.js

import { SHOW_PRODUCTS, SELECT_PRODUCT } from './constants';

export function showProducts(products) {
  return {
    type: SHOW_PRODUCTS,
    payload: products
  };
}

// component.js

import React, { Component } from 'react';
import axios from 'axios';
import { connect } from 'react-redux';

import ProductsList from './ProductsList';
import { showProducts }  from '../actions/products';


class Home extends Component {
  constructor(props) {
    super(props);
  }

  componentWillMount() {
    this.props.getProducts(); 
  }

  render() {
    return(
      <div>Home Page
        <ProductsList />
      </div>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    productsList: state.productsReducer.productsList
  };
}

const mapDispatchToProps = (dispatch) => {
  return {
    getProducts: () => {
      axios.get('http://localhost:5000/product/list')
      .then((res) => {
        console.log(res.data);
        dispatch(showProducts(res.data))
      })
      .catch(err => console.log(err))
    }
  }
}

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

I am also including a link to an image with my redux logger.

https://i.sstatic.net/bTnYh.png

There's probably a very small, stupid mistake in here as I'm quite new to React and completely new to Redux

2
  • Can you verify if payload have items on productsReducer file? Commented Feb 14, 2018 at 23:09
  • have you console.log() the action in the productsReducer? Commented Feb 14, 2018 at 23:19

4 Answers 4

1

You have a mistake, and I don't know if you a linter but in productsReducer.js you are importing constants from actions when it should be from constants:

import { SHOW_PRODUCTS, SELECT_PRODUCT } from '../actions/constants'; // <- from constants instead

const initialState = {
  productsList: []
};

const productsReducer = (state = initialState, action) => {
  switch (action.type) {
    case SHOW_PRODUCTS: 
      return {...state, productsList: action.payload}
  }
  return state;
}

export default productsReducer;

So your reducer shouldn't be actually taken the proper case since it is undefined and It will so return the initial state.

Sign up to request clarification or add additional context in comments.

2 Comments

I have folder called actions where I also put my constants file, so it is imported correctly. That might be just a bad way of organizing my files, I don't know. if you look at the link I posted i.sstatic.net/bTnYh.png. the action payload actually returns correct data from the action.payload
It turns out I was importing it from a wrong path...I wasted all day trying to figure it out...just to notice it the next morning...Thanks for your help
0

I believe in mapStateToProps you're going to want to do the following:

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

To confirm productsList being passed through, can you add in a simple loop to the render function of component.js like below:

render() {
    const { productsList } = this.props;
    return(
        <div>
            Home Page
            {productsList.map((product, index) => (
                <div key={index}>{product.PROPERTY_NAME_HERE}</div>
            ))}
        </div>
    )
}

5 Comments

Couple more things, can you elaborate the purpose of this.props.getProducts(); in componentWillMount() lifecycle event of component.js and also, you may want to pass productsList from component.js render method: <ProductList productsList={this.props.productsList} />
And finally, can you share code for ProductList component?
Yeah...there's nothing there for now...I got stuck with not being able to update my state so as of now I render it in this component. Well, the purpose of this.props.getProducts() is to fire this function when component mounts
Perhaps you can replace ProductList component with a simple loop for now to confirm productsList being retrieved correctly, I've added render method code as an example
Thanks, but the problem is redux is returning an empty array in my state
0

The way I do it with my reducer is

import { SHOW_PRODUCTS, SELECT_PRODUCT } from '../actions/products';

const initialState = {
  productsList: []
};

const productsReducer = (state = initialState, action) => {
  switch (action.type) {
    case SHOW_PRODUCTS:
      let nextState = {...state};
      nextState.productsList = action.payload
      return nextState;
  }
  return state;
}

export default productsReducer;

Comments

0

Try this way:

componentWillMount() {
  this.getProducts(); 
}

getProducts() {
  axios.get('http://localhost:5000/product/list')
  .then((res) => {this.props.showProducts(res.data);})
  .catch(err => console.log(err));
}

const mapDispatchToProps = dispatch => ({
  showProducts: (data) => {
    dispatch(showProducts(data));
  },
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.