0

I'm fetching an array from the backend, it works, but redux is somehow not assigning the array to a variable. products in initialState is always empty and if I try to reference it in my component, it is undefined.

RestActions:

const receivedProducts = (products) => ({
    type: "RECEIVED_PRODUCTS",
    products
})


export function getProducts() {
    return function(dispatch) {
        return axios({
            url: '/products',
            timeout: 20000,
            method: 'get'
        })
        .then(function(response) {
            let p = response.data;
            dispatch(receivedProducts(p));
        })
        .catch(function(error) {
            if(error.response) {
                // DEBUGGING
                console.log(error.response.data);
                console.log(error.response.status);
                console.log(error.response.headers);
            }
        })
    }
};

I placed my reducer in the store. This is what it looks like.

Store

const initialState = {

    // KEYBOARD
    searchWord: '',

    // BASKET
    basket:[],

    // PRODUCTS
    products: []
};
const reducer = (state = initialState, action) => {
    console.log('reducer', action);
    console.log('basket', state.basket);
    console.log('products', state.products)
    switch(action.type) {

        // REST
        case 'RECEIVED_PRODUCTS':
            return Object.assign({}, state, {products: action.products});
        ...

My component dynamically creates buttons based on products and renders them in a grid. Whenever I call this.props.products.length, it is undefined. This is the component:

Buttons

class ButtonsGrid extends React.Component {

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

    addProduct = (product) => {
        this.props.onButtonPress(product);
    }

    render() {   
        const {classes} = this.props;
        return (
            <div>
                <GridList cellHeight={50} cols={10}>
                    {this.props.list.length > 0 ? this.props.list.map(product => {
                        return (
                            <Button key={Math.random()} style={{width: '200px', border: '1px solid'}} variant="raised" color="primary" onClick={() => this.addProduct(product)}>
                                <div 
                                    style={{fontSize:'12px', display: 'flex', justifyContent: 'center', textAlign:'center'}}>
                                        {product.name}
                                </div>
                            </Button>
                        );
                    }) : ''}
                </GridList>
            </div>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        basket: state.basket,
        products: state.products
    }
}

const mapDispatchToProps = (dispatch) => {
    return { 
        onButtonPress: (data) => {
            let action = { type: 'PRODUCT_ADD', product: data };
            dispatch(action);
        },
        getProducts : function() {
            dispatch(getProducts());
        }
    };
}

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

Then it gets called in App.js

App.js

<ButtonsGrid store={store} list={this.state.list} clicked={this.clicked}/>

So, I can console.log('reducer', action); and it does print the right stuff, but I can't assign the data to products. I tried doing this but it still didn't work.

The data is just two json objects.

Any help is appreciated!

5
  • What error do you receive?(If any) Commented Mar 20, 2018 at 11:00
  • I check {this.props.list.length > 0 ? ...} before rendering the buttons in the Buttons component. I get length is undefined. I forgot to add products: state.products to Buttons' mapStateToProps and now I get TypeError: Cannot read property 'cols' of undefined . If I console.log() the products in the store, then I just get an empty array. Commented Mar 20, 2018 at 11:06
  • Okay, I am totally confused. I can log this.props.products successfully in ButtonsComponent and it prints an empty array. However if I try to map the objects to buttons in the loop, I get undefined. This is so confusing. Commented Mar 20, 2018 at 11:16
  • try doing console.log(this.props) in ButtonsGrid to see if this.props.list exists. Commented Mar 20, 2018 at 11:16
  • console.log(this.props) does work. this.props.list was just for testing before I integrated redux Commented Mar 20, 2018 at 11:21

1 Answer 1

2

Spread the state object

 return Object.assign({}, ...state, {
  products: [
    ...state.products,
    action.products
  ]
});
Sign up to request clarification or add additional context in comments.

10 Comments

I am not using combineReducers.
Could you please console state in mapStateToProps and shared the outut
If I try to map the objects to buttons in ButtonsGrid like this {this.props.products.length > 0 ? this.props.products.map(product => { - I'm getting a TypeError: Cannot read property 'cols' of undefined
@Claim0013 not like this. Please check EDIT.Only state second param
@Claim0013 [...this.state.products, action.products] I missed it.my bad. Its way of concat the existing and new element of the array.
|

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.