Search code examples
reactjsreduxaxiosmaterial-uiredux-toolkit

How to use react redux to show data that comes from an api inside an option select?


After making the request for a locale API, I have to get the response data and put it inside a select. To find out if the request was ok, I made a console.log (DATA STATE) and got the following return:


DATA STATE 
{data: Array(27), status: 200, statusText: "OK", headers: AxiosHeaders, config: Object…}

I tried to map the state select inside the component (states->index.js) , however, no information is returned. My goal is that when selecting a state (data.nome) (states->index.js) the cities of state appear in the component (city->index.js).

Code statesSlice.js

import React, { useState, useEffect } from "react";
import { FormControl, InputLabel, MenuItem, Select } from "@mui/material";
import { useDispatch, useSelector } from "react-redux";
import { getStates } from "../states/statesSlice";

export const SelectState = () => {
  const dispatch = useDispatch();
  const states = useSelector((state) => state.states.dataState);
  const [stateSelected, setStateSelected] = useState("");

  useEffect(() => {
    dispatch(getStates());
  }, [dispatch]);

  const handleChange = (event) => {
    dispatch(setStateSelected(event.target.value));
  };

  return (
    <FormControl sx={{ m: 1, minWidth: 120 }} size="small">
      <InputLabel id="demo-select-small">State</InputLabel>
      <Select
        labelId="demo-select-small"
        id="demo-select-small"
        value={stateSelected}
        label="estados"
        onChange={handleChange}
      >
        <MenuItem disabled>Select a state</MenuItem>
        {states.length > 0 &&
          states.map((item) => (
            <MenuItem key={item.id} value={item.sigla}>
              {item.nome}
            </MenuItem>
          ))}
      </Select>
    </FormControl>
  );
};

What can I try next? I'm new to Redux. I already created the store.js, slices and provider in index.js.


Solution

  • You can add setState function this way:

    export const setState = createAsyncThunk(
      "state/setState",
      async (selectedState, { rejectWithValue }) => {
        try {
          return selectedState;
        } catch (err) {
          return rejectWithValue([], err);
        }
      }
    );
    

    And in the reducers list,

        builder.addCase(setState.fulfilled, (state, action) => {
          state.selectedState = action.payload;
        });
    

    And then call the setState function to set the selected state:

    dispatch(setState(e.target.value));
    

    The same approach has been applied to getCities as well.

    The code is a bit lengthy, but I guess this might be better for the maintenance and expansion of the codebase in the future.

    The working demo is here: https://codesandbox.io/s/createasyncthunk-createslice-redux-forked-9qwene?file=/src/features/states/statesSlice.js