我制作了一个简单的待办事项列表应用程序来学习Redux Toolkit,在没有后端的情况下让它工作后,我决定添加一个简单的Flask服务器来练习使用Redux Toolkit的createAsyncThunk
我成功地创建了3个不同的异步thunk,用于用户获取他们的to-do、发布新的to-do或放置to-do。
import { createSlice, current, createAsyncThunk } from '@reduxjs/toolkit';
import axiosPrivate from '../../api/axios';
const initialState = {
toDos: []
}
export const getToDos = createAsyncThunk('toDo/getToDos', async (user) => {
const response = await axiosPrivate.get(`/to-dos/${user?.user?.firebase_uid}`, { headers: { 'Authorization': user?.idToken }, withCredentials: true });
return response.data
})
export const addToDo = createAsyncThunk('toDo/addToDo', async ({ user, newToDo }) => {
const response = await axiosPrivate.post('/to-dos/new', { userId: user?.user?.id, firebaseUid: user?.user?.firebase_uid, task: newToDo?.task }, { headers: { 'Authorization': user?.idToken }, withCredentials: true });
const data = response.data
return {data, user}
})
export const updateToDo = createAsyncThunk('toDo/updateToDo', async ({ user, toDoId, updateAttributes }) => {
const response = await axiosPrivate.put('/to-dos/update', { userId: user?.user?.id, firebaseUid: user?.user?.firebase_uid, toDoId: toDoId, updateAttributes}, { headers: { 'Authorization': user?.idToken }, withCredentials: true })
const data = response.data
return {data, user}
})
export const toDosSlice = createSlice({
name: 'toDos',
initialState,
reducers: {},
extraReducers(builder) {
builder
.addCase(getToDos.fulfilled, (state, action) => {
state.toDos = action.payload?.toDos
})
.addCase(addToDo.fulfilled, (action) => {
getToDos(action?.payload?.user); // This does not change anything
})
.addCase(updateToDo.fulfilled, (action) => {
getToDos(action?.payload?.user); // This does not change anything
})
}
})
export const { deleteToDo } = toDosSlice.actions;
export const selectToDos = (state) => state.toDos;
export default toDosSlice.reducer;
我遇到的问题是,在用户编辑了他们的toDo并将其标记为完成后,我不确定在哪里以及如何正确地从后端获取to-do。我知道我可以使用redux状态从技术上设置toDo的状态,并验证POST或PUT是否成功,尽管我想了解如何在此后使用GET请求正确地完成。
我的ToDoList
组件,用户可以在其中删除或放置他们的ToDos,如下所示:
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import Stack from '@mui/material/Stack';
import Divider from '@mui/material/Divider';
import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import IconButton from '@mui/material/IconButton';
import DeleteIcon from '@mui/icons-material/Delete';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import Checkbox from '@mui/material/Checkbox';
import Typography from '@mui/material/Typography';
import { getToDos, updateToDo, selectToDos } from '../toDoSlice';
import useAuth from '../../../hooks/useAuth';
function ToDoList() {
const dispatch = useDispatch();
const { user } = useAuth();
const toDos = useSelector(selectToDos);
useEffect(() => {
dispatch(getToDos(user));
}, [dispatch, user])
const handleChange = (toDoId, updateAttributes) => {
dispatch(updateToDo({ user, toDoId, updateAttributes }));
// dispatch(getToDos(user)); // This sometimes causes the GET request to occur before the PUT request, which I don't understand
}
return (
<Stack spacing={2}>
<Divider sx={{ marginTop: 5 }} />
<Grid xs={4} item>
{toDos?.toDos?.length ?
<Box>
<List>
{toDos?.toDos?.map((toDo) => (
<ListItem
key={toDo?.id}
secondaryAction={
<IconButton
edge="end"
onClick={() => handleChange(toDo?.id, { 'deleted': !toDo?.deleted })}
>
<DeleteIcon />
</IconButton>
}
>
<ListItemButton onClick={() => handleChange(toDo?.id, { 'completed': !toDo?.completed })}>
<ListItemIcon>
<Checkbox
name={toDo.task}
checked={toDo.completed}
edge='start'
/>
</ListItemIcon>
<ListItemText
primary={toDo.task}
sx={{ textDecoration: toDo.completed ? 'line-through' : null }}
primaryTypographyProps={{
style: {
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
}
}}
/>
</ListItemButton>
</ListItem>
))}
</List>
</Box>
: <Typography align='center' variant="h6" component="div" mt={2}>No To-Dos</Typography>
}
</Grid >
</Stack >
)
}
export default ToDoList
如何在POST或PUT操作之后执行GET请求?然后我应该将分派(getToDos(user))放在哪里?代码中的注解显示了我已经尝试过的方法的结果
1条答案
按热度按时间mxg2im7a1#
在再次阅读Redux-Toolkit文档并查看其他SO帖子之后,我了解了执行asyncThunk连续调用的正确方法。
我没有在切片中执行它们,而是将调用移到了组件中,并使用Promises来执行它们。为了从请求中捕获错误并在组件中访问它,您必须在asyncThunk中使用Toolkit的
rejectWithValue
参数。下面是一个例子:
通过将
{ rejectWithValue }
添加到参数和return rejectWithValue(err.response.data)
,您可以访问组件中的响应,如下所示: