You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Redux如何将API数据展示在Select并实现州城联动?

问题分析与解决方案

核心问题定位

  1. Redux数据存储错误:你的API返回的是包含data数组的响应对象,但当前slice可能把整个响应对象存在了dataState里,导致组件中states不是数组,无法执行map渲染选项。
  2. 本地状态调用错误:handleChange里错误地用dispatch调用组件本地的setStateSelected,这是React useState的setter,不需要Redux dispatch。
  3. 缺少城市数据联动逻辑:未实现选中州后触发城市数据请求的逻辑。

步骤1:修正States Slice的数据存储

首先确保你的statesSlice.js正确提取API响应中的数组并存储:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';

// 定义获取州数据的异步action
export const getStates = createAsyncThunk(
  'states/getStates',
  async () => {
    const response = await axios.get('你的本地API地址');
    // 提取响应中的data数组(根据你的API返回结构调整)
    return response.data.data;
  }
);

const initialState = {
  data: [], // 存储州的数组
  status: 'idle', // 标记请求状态:idle/loading/succeeded/failed
  error: null
};

const statesSlice = createSlice({
  name: 'states',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(getStates.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(getStates.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.data = action.payload; // 将数组存入state.data
      })
      .addCase(getStates.rejected, (state, action) => {
        state.status = 'failed';
        state.error = action.error.message;
      });
  }
});

export default statesSlice.reducer;

步骤2:修复SelectState组件

调整组件中数据获取和状态更新逻辑:

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";
import { getCitiesByState } from "../cities/citiesSlice"; // 后续会创建的城市slice

export const SelectState = () => {
  const dispatch = useDispatch();
  // 正确获取Redux中的州数组
  const states = useSelector((state) => state.states.data);
  const statesStatus = useSelector((state) => state.states.status);
  const [stateSelected, setStateSelected] = useState("");

  // 初始化请求州数据
  useEffect(() => {
    if (statesStatus === 'idle') {
      dispatch(getStates());
    }
  }, [dispatch, statesStatus]);

  // 选中州后,触发对应城市的请求
  useEffect(() => {
    if (stateSelected) {
      dispatch(getCitiesByState(stateSelected));
    }
  }, [dispatch, stateSelected]);

  // 直接调用本地setter更新选中状态,无需dispatch
  const handleChange = (event) => {
    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是数组,可以正常map渲染 */}
        {states.map((item) => (
          <MenuItem key={item.id} value={item.sigla}>
            {item.nome}
          </MenuItem>
        ))}
      </Select>
    </FormControl>
  );
};

步骤3:创建Cities Slice实现联动

新建citiesSlice.js,用于处理城市数据请求:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';

// 根据州缩写获取城市数据
export const getCitiesByState = createAsyncThunk(
  'cities/getCitiesByState',
  async (stateSigla) => {
    const response = await axios.get(`你的本地城市API地址?state=${stateSigla}`);
    return response.data.data; // 同样根据API返回结构调整
  }
);

const initialState = {
  data: [],
  status: 'idle',
  error: null
};

const citiesSlice = createSlice({
  name: 'cities',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(getCitiesByState.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(getCitiesByState.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.data = action.payload;
      })
      .addCase(getCitiesByState.rejected, (state, action) => {
        state.status = 'failed';
        state.error = action.error.message;
      });
  }
});

export default citiesSlice.reducer;

步骤4:创建SelectCity组件

新建城市选择组件,渲染Redux中的城市数据:

import React, { useState } from "react";
import { FormControl, InputLabel, MenuItem, Select } from "@mui/material";
import { useSelector } from "react-redux";

export const SelectCity = () => {
  const cities = useSelector((state) => state.cities.data);
  const [citySelected, setCitySelected] = useState("");

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

  return (
    <FormControl sx={{ m: 1, minWidth: 120 }} size="small">
      <InputLabel id="demo-select-city">City</InputLabel>
      <Select
        labelId="demo-select-city"
        id="demo-select-city"
        value={citySelected}
        label="cities"
        onChange={handleChange}
        disabled={cities.length === 0}
      >
        <MenuItem disabled>Select a city</MenuItem>
        {cities.map((city) => (
          <MenuItem key={city.id} value={city.nome}>
            {city.nome}
          </MenuItem>
        ))}
      </Select>
    </FormControl>
  );
};

步骤5:更新Store配置

在store.js中添加城市reducer:

import { configureStore } from '@reduxjs/toolkit';
import statesReducer from './states/statesSlice';
import citiesReducer from './cities/citiesSlice';

export const store = configureStore({
  reducer: {
    states: statesReducer,
    cities: citiesReducer
  }
});

内容的提问来源于stack exchange,提问作者Begginer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 07:05:33