Vmxes
Vmxes

Reputation: 2755

React Redux store update doesn't trigger component rerender

I'm new in Redux and have a problem with rerendering after the store changed. I have found many similar problems here on SO but still can't solve my issue.

I have a monthly task(event) calendar with multiple tasks. The Calendar is the main component and some level deeper there are multiple TaskItem components. At the first render, the calendar and the tasks are rendered fine (In this case without employee names). In the Calendar component I trigger loading employees with a useEffect hook. I can see the network request on my console. Besides this, the console logs in the action, and in the reducer also show the employee list. And the Redux devtool also shows the loaded employees. Still the mapStateToProps on TaskItem shows a completly empty state.

What I'm doing wrong?

Here is my related code:

Calendar:

const Calendar = ({startDay, tasks, loadEmployeesAction}) => {

        useEffect(()=>{
            loadEmployeesAction();
        },[]);

        ...
}

export default connect(null, {loadEmployeesAction})(Calendar);

TaskItem:

const TaskItem = ({task, onTextEdit, onTaskView, saveTask, employees }) => {

    ...
}

const mapStateToProps = (state) => {
    console.log('Actual state is: ', state);
    return {
        employees: state.employees
    }
}

export default connect(mapStateToProps)(TaskItem);

Reducer:

export const employeeReducer = (state = [], action) => {
    switch (action.type) {
        case actionType.EMPLOYEES_LOADED:
            console.log('Reducer - Employees loaded:', action );
            return action.payload.employees;
        default :
            return state;
    }
}

Actions:

const employeesLoaded = (employees) => {
    return {type: actionType.EMPLOYEES_LOADED, payload: {
            employees
        }
    }
}

export const loadEmployeesAction = () => {
    return (dispatch) => {
        return employeeApi.getAllEmployees().then(emps => {
            console.log('Action - Employees loaded: ', emps);
            dispatch(employeesLoaded(emps));
        })

    }
}

Root reducer:

export const rootReduxReducer = combineReducers({
    employees: employeeReducer
});

Upvotes: 1

Views: 716

Answers (2)

Vmxes
Vmxes

Reputation: 2755

I found the error. It was a very clumsy mistake.

All of my posted code was fine, but I put the store creation in a component that was rerendered again and again so my store was recreated again and again.

Upvotes: 1

Aswin_Pradeep
Aswin_Pradeep

Reputation: 111

The reducer code seems to be not as the redux pattern. So usually the state object is not directly replaced with a different object. Instead only the part of the state that needs to be changed is only with some non-mutating operation like spread operator.

So I think the reducer code should be changed like

export const employeeReducer = (state = [], action) => {
switch (action.type) {
    case actionType.EMPLOYEES_LOADED:
        return {...state,employees:action.payload.employees}
    default :
        return state;
}
}

if the response from the API is in the form

[{"employee_name":"name","employee_age":24},.....]

Upvotes: 0

Related Questions