我使用react-redux
与@reduxjs/toolkit
进行全局状态管理,在我的商店中,我有sliceOne
与初始状态和减速机。我试图在useSelector()
组件中使用状态值,但它显示出承诺而不是更新的值。在该组件中调度动作。
存储/sliceOne.js
import { createSlice } from "@reduxjs/toolkit";
const sliceOne = createSlice({
name: "sliceOne",
initialState: {
firstName: "first",
lastName: "last",
age: 10,
product: {},
},
reducers: {
async action1(state) {
const res = await fetch(`https://fakestoreapi.com/products/2`);
const data = await res.json();
state.product = data;
},
},
});
export const sliceOneActions = sliceOne.actions;
export default sliceOne;
组件
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { sliceOneActions } from "../store/slice-one";
const Compo = () => {
const dispatch = useDispatch();
useEffect(dispatch(sliceOneActions.action1()), []); // without calling this getting state value but with this getting promise
let data = useSelector((state) => state);
console.log(data); //getting promise
return <div></div>;
};
export default Compo;
问题
- Reducer函数被认为是纯的,是同步的功能。如果你需要运行一些异步逻辑,那么你需要在异步中处理它。动作,又名Thunk。
- 组件错误地使用
useEffect
钩子,直接调用dispatch
代替useEffect
钩子回调函数。
解决方案将异步逻辑从reducer函数移到异步操作中。
- 创建异步Thunk函数,该函数发出GET请求并返回获取的数据。
- 在
sliceOne
切片的extraReducers
中添加一个case reducer来处理一个完成的action1
动作承诺。
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
const action1 = createAsyncThunk(
"sliceOne/action1",
async () => {
const res = await fetch("https://fakestoreapi.com/products/2");
const data = await res.json();
return data;
}
);
const sliceOne = createSlice({
name: "sliceOne",
initialState: {
firstName: "first",
lastName: "last",
age: 10,
product: {},
},
extraReducers: builder => {
builder
.addCase((action1.fulfilled, (state, action) => {
state.product = action.payload;
}));
},
});
export const sliceOneActions = {
...sliceOne.actions,
action1,
};
export default sliceOne;
修复UI正确使用useEffect
钩子来调度action1
动作。
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { sliceOneActions } from "../store/slice-one";
const Compo = () => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(sliceOneActions.action1());
}), []);
const data = useSelector((state) => state);
...
};
试试下面的代码:
reducers: {
action1: (state, action) => {
...state,
product: action.payload
}
},
useEffect(() => {
async function getProducts() {
const res = await fetch(`https://fakestoreapi.com/products/2`);
const data = await res.json();
dispatch(sliceOneActions.action1(data))
}
getProducts();
}, []);