Damien STEPHAN
Damien STEPHAN

Reputation: 143

React Redux : use Selector is called before dispatch

I'm creating a react app with redux.
I need the lists of french departements for all pages in my app, so I put it in redux state.

I dispatch the action in the App component in the useEffect hook (Note I use an other useEffect in the component, but when the action is in the other block it's not working too)

I have a page where I need to use this list, so I select it with the useSelector hook. But it returns an empty object, I have an error telling me dpts.map is not a function

I think the action is dispatching after the page has rendered, because I when I log the response of the api call in the action, it appears after the log of the useSelector result.

I'm using another state property in another page, but it seems to work with the other page.

App.jsx

const dispatch = useDispatch();
useEffect(() => {
        dispatch(getDpts());
}, [dispatch])

Here is the action associated with :

dpts.actions.js

import axios from "axios";

export const GET_DPTS = "GET_DPTS";
export const getDpts = () => {
    return async (dispatch) => {
        try {
            const res = await axios({
                method: "get",
                url: "https://geo.api.gouv.fr/departements",
            });
            console.log("done : " + res)
            dispatch({ type: GET_DPTS, payload: res.data });
        } catch (err) {
            (err) => console.log("DPTS FETCH ERROR --- " + err);
        }
    };
};

Map.jsx

function DptCtl() {
    // Control
    const map = useMap();

    // List of dpts and provinces
    const dpts= useSelector(dptsSelector);
    console.log(dpts);

    return (
        <>
            <input type="text" list="dpt-ctl-list" placeholder="Filtrer par département"/>
            <datalist id="dpt-ctl-list">
                {dpts.map((dpt, index) => 
                    <option value={dpt.code} key={index}>{dpt.nom}</option>
                )}
            </datalist>
        </>
    )
}

Upvotes: 2

Views: 1452

Answers (1)

Erfan
Erfan

Reputation: 1802

It depends on how you are initializing your state in the reducer.

for example you create a reducer with this initial state:

const initialState={}

later, based on actions, the state changes to this:

   {dpts:someDataArray}

the problem is that you have a dpts.map somewhere in your app, since dpts is undefined in the beginning you receive that error that dpts.map is not a function.

the solution to this is simply put dpts in the initialState as an empty array:

    const initialState={dpts:[]}

if that is not the issue with your code, meaning dpts isn't undefined in the initialState, it is probably initialized as a string or an object which don't have map methods.

Upvotes: 2

Related Questions