Lor*_*Dex 4 reactjs redux redux-toolkit
我创建了两个异步重击:
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
}
);
Run Code Online (Sandbox Code Playgroud)
基本上我试图在 React 组件的 useEffectfoo()内部调用bar()
,我bar()像这样调度:
React.useEffect( async () => {
await dispatch( bar() );
}, [bar]);
Run Code Online (Sandbox Code Playgroud)
foo正在派遣但bar没有。
我究竟做错了什么?
先感谢您。
编辑1。它有点像反模式,但我基本上想做的是链接 bar() 和 foo(),而且我不知道任何其他(正确的?)方式
编辑2。基于@Nadia Chibrikova 评论,这是我使用 thunkAPI 尝试过的:
export const bar = createAsyncThunk(
'slice/bar',
async ( thunkApi ) => {
thunkApi .dispatch(foo())
}
);
Run Code Online (Sandbox Code Playgroud)
但我收到以下错误:
Cannot read property 'dispatch' of undefined
Run Code Online (Sandbox Code Playgroud)
Lin*_*ste 12
这不是一个很好的设计模式,但它是可以做到的。您的“Edit2”很接近,但thunkApi它是有效负载创建者的第二个参数。第一个参数是您在调用动作创建者时传递的参数bar(args)。如果不需要参数,则可以使用 a_来表示该变量未使用。
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;
}
);
Run Code Online (Sandbox Code Playgroud)
调用dispatch(bar())将按以下顺序调度操作:
正如 @Marcus Melodious 所建议的,最好有完全独立的操作并在组件中处理分派。如果需要来自(例如 an或 a )bar的某些数据,那么它应该将该数据作为其操作创建者的参数。fooidtoken
这是一个示例,我们获取帖子,然后根据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();
}
);
Run Code Online (Sandbox Code Playgroud)
您可以使用一个useEffect并查看调度结果
useEffect(() => {
const execute = async () => {
const postAction = await dispatch(fetchPost(POST_ID));
const {userId} = postAction.payload;
dispatch(fetchUser(userId));
};
execute();
}, []);
Run Code Online (Sandbox Code Playgroud)
或者您可以从两个单独的挂钩发起两个请求useEffect。您的第二个钩子知道何时根据 Redux 状态的变化进行调度useSelector。
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/>;
};
Run Code Online (Sandbox Code Playgroud)
这是两个钩子方法的完整代码示例:
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>
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6991 次 |
| 最近记录: |