Skip to content
Advertisement

react-redux: actions do not change the store

I’m building a react app with redux and I have a problem.

I have a component connected to the redux store and even though I dispatch actions those actions are not received from the reducer thus the state won’t change.

Here’s the code of the component:

import React from "react";
import { connect } from "react-redux";

import { setOrderFilter } from "store/filters";

const mapStateToProps = (state) => {
    return {
        filters: state.entities.filters,
    };
};

const mapDispatchToProps = {
    setOrderFilter,
};

function Filters(props) {
    const { order } = props.filters;

    console.log(setOrderFilter({test: 1}) 
    // {type: "filters/setOrderFilter", payload: {…}}
    // payload: {test: 1}
    // type: "filters/setOrderFilter"

    const handleOrder = (event) => {
        setOrderFilter({ order: event.target.value });
    };

    return (
        <div>
            <label>
                Date order:
                <select value={order} onChange={(e) => handleOrder(e)}>
                    <option value="ascending">ascending</option>
                    <option value="descending">descending</option>
                </select>
            </label>
        </div>
    );
}

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

Here’s the filters.js file in the store:

import { createSlice } from "@reduxjs/toolkit";

const slice = createSlice({
    name: "filters",
    initialState: {
        order: "descending",
    },
    reducers: {
        setOrderFilter: (state, action) => {
            console.log("here");
            state.order = action.payload;
        },
    },
});

export const { setOrderFilter } = slice.actions;

export default slice.reducer;

Everything looks fine, even console.log the action setOrderFilter yields the correct result, but when I change the select in the UI, no action is dispatched and the value doesn’t change… the console.log inside the reducer is never printed.

The store is configured with an api middleware to handle async code:

import axios from "axios";
import * as actions from "store/api";

import getBaseUrl from "helpers/getApiUrl";

const api = ({ dispatch }) => (next) => async (action) => {
    console.log(action)
    if (action.type !== actions.apiCallBegan.type) return next(action);

    ....
};

export default api;

The calls from other entities are printed and visible in the middleware, the one from filters are not even printed there.

What am I missing?

Advertisement

Answer

The problem is in the handleOrder function.

const handleOrder = (event) => {
    setOrderFilter({ order: event.target.value });
};

You have to use the connected setOrderFilter. That is in the component’s props.

const handleOrder = (event) => {
    props.setOrderFilter({ order: event.target.value });
};

It’s an easy mistake to make when using the mapDispatchToProps shorthand. There is a function in scope called setOrderFilter, but when you use that, you will just create the action object, but it will not be dispatched to redux.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement