如何在Axios请求链接中使用Redux的state数据?
问题:如何在Redux Toolkit的异步请求中使用已更新的state值?
我是React和Redux新手,想要在imageSlice.js第17行的Axios请求链接中使用名为type的state数据。该type的值是通过另一个.jsx文件中的dispatch()方法设置的。在Home.jsx文件中,我在第24行通过点击事件调用dispatch来更新state值type。
相关代码
Home.jsx
import React from 'react'; import '../styles/home.scss'; import { Link } from 'react-router-dom'; import { setType } from '../redux/imageSlice'; import { useDispatch } from 'react-redux'; const Home = () => { const dispatch = useDispatch(); return ( <div className="container"> <div className="row"> <div className="col-sm-6 col-md-4 d-flex justify-content-center my-3"> <div className="ci"> <img className="img-fluid" src="https://res.cloudinary.com/djz3p8sux/image/upload/v1662295247/web-projects-images/natures_hodrkk.jpg" alt="Nature" /> <Link to="/nature"> <div className="middle"> <div className="text" onClick={() => dispatch(setType('nature'))}> Nature </div> </div> </Link> </div> </div> </div> </div> ); }; export default Home;
imageSlice.js
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; import axios from 'axios'; const initialState = { type: '', images: [], error: null, isLoading: false, }; const config = { Authorization: '563492ad6f91700001000001350d302e175b4c208aac413953d6edcc', }; export const fetchImages = createAsyncThunk('images/fetchImages', async () => { const res = await axios.get( `https://api.pexels.com/v1/search?query=${initialState.type}&per_page=15`, { headers: config, } ); return res.data; }); export const imageSlice = createSlice({ name: 'images', initialState, reducers: { setType: (state, action) => { state.type = action.payload; }, }, extraReducers: builder => { builder.addCase(fetchImages.pending, state => { state.isLoading = true; }); builder.addCase(fetchImages.fulfilled, (state, action) => { state.isLoading = false; state.images = action.payload; state.error = null; }); builder.addCase(fetchImages.rejected, (state, action) => { state.isLoading = false; state.images = []; state.error = action.error.message; }); }, }); export const { setType } = imageSlice.actions; export default imageSlice.reducer;
store.js
import { configureStore } from '@reduxjs/toolkit'; import imageReducer from './imageSlice'; export const store = configureStore({ reducer: { images: imageReducer, }, });
解决方案
1. 修改fetchImages异步Thunk,获取当前最新state
createAsyncThunk允许我们通过第二个参数thunkAPI访问Redux store的当前状态。你需要修改fetchImages的定义,用thunkAPI.getState()获取最新的type值,而不是直接使用initialState.type(初始值不会随state更新而变化)。
修改后的fetchImages代码:
export const fetchImages = createAsyncThunk('images/fetchImages', async (_, thunkAPI) => { // 获取当前store的全部状态 const currentState = thunkAPI.getState(); // 从状态中取出更新后的type值 const currentType = currentState.images.type; const res = await axios.get( `https://api.pexels.com/v1/search?query=${currentType}&per_page=15`, { headers: config, } ); return res.data; });
2. 确保在type更新后触发请求
你需要在设置type之后调用fetchImages,确保请求使用的是最新的type值。比如修改Home.jsx中的点击事件:
<div className="text" onClick={() => { dispatch(setType('nature')); // 设置完type后立即触发请求 dispatch(fetchImages()); }}> Nature </div>
或者,如果你是在跳转到的页面(比如/nature)中展示图片,可以在目标页面用useEffect监听type的变化,自动触发请求:
// 示例:Nature.jsx import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { fetchImages } from '../redux/imageSlice'; const Nature = () => { const dispatch = useDispatch(); const { type, images, isLoading, error } = useSelector(state => state.images); useEffect(() => { // 当type存在且有值时,触发请求 if (type) { dispatch(fetchImages()); } }, [dispatch, type]); // 渲染图片列表等内容 return ( <div> {isLoading && <p>加载中...</p>} {error && <p>出错了:{error}</p>} <div className="image-grid"> {images?.photos?.map(img => ( <img key={img.id} src={img.src.medium} alt={img.alt} /> ))} </div> </div> ); }; export default Nature;
3. 处理空值情况(可选)
为了避免type为空时发起无效请求,可以在fetchImages中添加判断逻辑:
export const fetchImages = createAsyncThunk('images/fetchImages', async (_, thunkAPI) => { const currentState = thunkAPI.getState(); const currentType = currentState.images.type; // 如果type为空,拒绝请求并返回错误信息 if (!currentType) { return thunkAPI.rejectWithValue('查询类型不能为空'); } const res = await axios.get( `https://api.pexels.com/v1/search?query=${currentType}&per_page=15`, { headers: config, } ); return res.data; });
内容的提问来源于stack exchange,提问作者Anikul Islam
相关产品推荐
相关产品推荐

