- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我创建了两个异步 thunk:
export const foo = createAsyncThunk(
'slice/foo',
async ( ) => {
const res = await fetch('/')
return res.data
}
);
export const bar = createAsyncThunk(
'slice/bar',
async ( ) => {
const res = await foo()
return res.data
}
);
基本上我试图在 bar()
内调用 foo()
然后在 react 组件的 useEffect 中,我像这样调度 bar()
:
React.useEffect( async () => {
await dispatch( bar() );
}, [bar]);
foo
正在调度,但 bar
没有。
我做错了什么?
提前谢谢你。
编辑1。感觉有点像反模式,但我基本上想做的是链接 bar() 和 foo(),我不知道任何其他(正确的?)方式
编辑2。基于@Nadia Chibrikova 的评论,这也是我使用 thunkAPI 尝试过的:
export const bar = createAsyncThunk(
'slice/bar',
async ( thunkApi ) => {
thunkApi .dispatch(foo())
}
);
但我收到以下错误:
Cannot read property 'dispatch' of undefined
最佳答案
这不是一个很好的设计模式,但它可以完成。您的“Edit2”很接近,但 thunkApi
是有效负载创建者的 second 参数。第一个参数是当您将 Action 创建者称为 bar(args)
时传递的参数。如果您不需要参数,则可以使用 _
表示该变量未使用。
export const foo = createAsyncThunk(
"slice/foo",
async () => {
const res = await fetch("/");
return res.json();
}
);
export const bar = createAsyncThunk(
"slice/bar",
async (_, { dispatch }) => {
const fooAction = await dispatch(foo());
return fooAction.payload;
}
);
调用 dispatch(bar())
将按以下顺序调度操作:
按照@Marcus Melodious 的建议,最好有完全独立的操作并处理组件中的调度。如果 bar
需要来自 foo
的一些数据(例如 id
或 token
),那么它应该采用该数据作为其 Action 创建者的参数。
这是一个示例,我们获取一个帖子,然后根据该帖子的 userId
属性获取用户配置文件。
export const fetchPost = createAsyncThunk(
"slice/fetchPost",
async (postId) => {
const res = await fetch(
`https://jsonplaceholder.typicode.com/posts/${postId}`
);
return res.json();
}
);
export const fetchUser = createAsyncThunk(
"slice/fetchUser",
async (userId) => {
const res = await fetch(
`https://jsonplaceholder.typicode.com/users/${userId}`
);
return res.json();
}
);
您可以使用一个 useEffect
并查看调度的结果
useEffect(() => {
const execute = async () => {
const postAction = await dispatch(fetchPost(POST_ID));
const {userId} = postAction.payload;
dispatch(fetchUser(userId));
};
execute();
}, []);
或者您可以从两个单独的 useEffect
Hook 发起两个请求。你的第二个钩子(Hook)知道何时根据 useSelector
中 Redux 状态的变化进行调度。
const Test = () => {
const dispatch = useDispatch();
const post = useSelector((state) => state.slice.post);
const user = useSelector((state) => state.slice.user);
const POST_ID = 1; // just a dummy constant for testing
console.log(post, user);
useEffect(() => {
const loadPost = async () => {
dispatch(fetchPost(POST_ID));
};
loadPost();
}, []); // run once on mount
useEffect(() => {
const loadUser = async (userId) => {
dispatch(fetchUser(userId));
};
// check if post has has been set and has a userId
if ( post && post.userId ) {
loadUser(post.userId);
}
}, [post]); // run when post changes
return <div/>;
};
这是两个钩子(Hook)方法的完整代码示例:
import {
createAsyncThunk,
configureStore,
createSlice
} from "@reduxjs/toolkit";
import { Provider, useDispatch, useSelector } from "react-redux";
import React, { useEffect } from "react";
export const fetchPost = createAsyncThunk(
"slice/fetchPost",
async (postId) => {
const res = await fetch(
`https://jsonplaceholder.typicode.com/posts/${postId}`
);
return res.json();
}
);
export const fetchUser = createAsyncThunk(
"slice/fetchUser",
async (userId) => {
const res = await fetch(
`https://jsonplaceholder.typicode.com/users/${userId}`
);
return res.json();
}
);
const slice = createSlice({
name: "slice",
initialState: {
user: undefined,
post: undefined
},
reducers: {},
extraReducers: {
[fetchPost.fulfilled]: (state, action) => {
state.post = action.payload;
},
[fetchUser.fulfilled]: (state, action) => {
state.user = action.payload;
}
}
});
const store = configureStore({ reducer: { slice: slice.reducer } });
const PostHeader = ({ postId }) => {
const dispatch = useDispatch();
const post = useSelector((state) => state.slice.post);
const user = useSelector((state) => state.slice.user);
console.log(post, user);
useEffect(() => {
const loadPost = async () => {
dispatch(fetchPost(postId));
};
loadPost();
}, [postId, dispatch]); // run once on mount
useEffect(() => {
const loadUser = async (userId) => {
dispatch(fetchUser(userId));
};
// check if post has has been set and has a userId
if (post && post.userId) {
loadUser(post.userId);
}
}, [post, dispatch]); // run when post changes
return (
<div>
{!!post && <h1>{post.title}</h1>}
{!!user && <h2>By {user.name}</h2>}
</div>
);
};
export default function App() {
return (
<Provider store={store}>
<PostHeader postId={1} />
</Provider>
);
}
关于reactjs - 如何在另一个 asyncThunk 中调度 asyncThunk,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66613260/
我是一名优秀的程序员,十分优秀!