Stepan Kolomiyets
Stepan Kolomiyets

Reputation: 39

Component can't catch up with redux state

Help me please solve this issue. I use redux and react-redux to control state in my app. But when I try to change styles in my Component depending in the value from redux store, it react with delay. When I add new Item and click the list and expect its color being changed, it does this only after I add another item, so that it always delays. Here is my reducer

export const items = (state = [], action) => {
switch(action.type) {
    case 'ADD_ITEM':
        const newItem = {
            title: action.title,
            id: action.id,
            selected: action.selected,
            comments: action.comments
        };
        return [
            ...state,
            newItem
        ];
    case 'REMOVE_ITEM':
        return state.filter(({ id }) => id !== action.id);
    case 'SELECT_ITEM':
        state.map((item) => {
            if (item.id === action.id) {
                return [
                    ...state,
                    item.selected = true
                ];
            } else {
                return [
                    ...state,
                    item.selected = false
                ];
            }
        });
    default:
        return state;
}
};

Here is my component which I want to react on every change of the redux store

import React from 'react';
import { connect } from 'react-redux';
import { removeItem, selectItem } from '../actions/items';
import { Badge, ListGroup, ListGroupItem, Button } from 'reactstrap';

const stylesForActiveItem = {
    borderLeft: '4px solid red',
    transition: 'all .5s',
    marginLeft: '-4px',
    borderRadius: '0'
}

class Item extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        const { removeItem, selectItem, id, title, selected } = this.props;
        return (
            <ListGroup className="Item">
                <ListGroupItem 
                    onClick={() => selectItem({ id })}
                    className={selected ? 'Item__text active-item' : 
'Item__text'}
                >{title} <Badge className="Item__badge">14</Badge>
            </ListGroupItem>
            <Button className="Item__btn" onClick={() => removeItem({ id 
})}>Delete</Button>
        </ListGroup>
    );
}
}

const mapDispatchToProps = (dispatch) => ({
removeItem: (id) => dispatch(removeItem(id)),
selectItem: (id) => dispatch(selectItem(id))
})

export default connect(null, mapDispatchToProps)(Item);

Upvotes: 0

Views: 86

Answers (1)

Karan Jariwala
Karan Jariwala

Reputation: 727

  state.map((item) => {
            if (item.id === action.id) {
                return [
                    ...state,
                    item.selected = true
                ];
            } else {
                return [
                    ...state,
                    item.selected = false
                ];
            }
        });

//I guess you need to do something like this



state.map((item) => {
            if (item.id === action.id) {
                return {...item, selected:true}

            } else {
                return {...item, selected:false}

            }
        });

Since even though map returns new array, internal object should also not get mutated. That is why we spread and create a new item object inside. There is no need to create arrays again in map with entire state. That will just change your state structure instead of just changing a boolean.

Upvotes: 1

Related Questions