reactjs redux thunk不会从API中删除项

wbrvyc0a  于 2022-12-18  发布在  React
关注(0)|答案(2)|浏览(121)

我的应用程序是一个简单的书店,我使用这个API https://www.notion.so/Bookstore-API-51ea269061f849118c65c0a53e88a739我能够得到书籍和张贴书籍whitout问题,但当我删除书籍,它在UI中工作,但当我刷新页面的书籍刚刚回来,所以不是从API中删除书籍。
这是我的减速器

const bookReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD:
      return [
        ...state, action.book,
      ];
    case REMOVE: 
    return state.filter((book) => book.item_id !== action.book.item_id);
    case FETCH_BOOKS: {
      const bookList = [];
      Object.entries(action.books).forEach(([key, value]) => bookList.push({
        item_id: key,
        title: value[0].title,
        author: value[0].author,
        category: value[0].category,
      }));
      return bookList;
    }
    default:
      return state;
  }
};

这是我删书的动作:第一个删除操作

export const removeBook = (book) => ({
  type: REMOVE,
  book,
});

然后我使用thunk的动作

export const deleteBooks = createAsyncThunk(REMOVE, async (bookId, thunkAPI) => {
  const response = await fetch(`${BOOK_URL}/${bookId}`,  {
   method: 'DELETE',
    body: JSON.stringify({
      item_id: bookId
    }),
    headers: {
      'Content-Type': 'application/json',
    },
  });
  await thunkAPI.dispatch(removeBook(bookId));
  return response.data;
});


这是我调用deleteBooks的函数

function Book({title, author, item_id, category}) {
  const dispatch = useDispatch();
  const deleteHandler = (id) =>{
    console.log(id);
    dispatch(deleteBooks(id))
  }
  return (
    <>
      <span>
        {title}
        </span>
        <br/>
        <span>
        {author}
      </span>
      <br/>
      <span>
        {category}
      </span>
      <br/>
      <button
        type="button"
        onClick={() => deleteHandler({item_id})}
      >
        Remove
      </button>
    </>
  );
}
zour9fqk

zour9fqk1#

你必须在查询参数中传递图书ID,而不是像API文档中解释的那样在正文中传递。这可能对你有用。

export const deleteBooks = createAsyncThunk(REMOVE, async (bookId, thunkAPI) => {
  const response = await fetch(`${BOOK_URL}/books/${bookId}`,  {
   method: 'DELETE',
    body: {},
    headers: {
      'Content-Type': 'application/json',
    },
  });
  await thunkAPI.dispatch(removeBook(bookId));
  return response.data;
});

这在您提供的文档中提到为:

ergxz8rk

ergxz8rk2#

问题

从我所能读到的代码来看,它出现在某个时候,当启动删除一本书的过程时,你会在沿着的某个地方掉下正确的id。
1.用户点击“删除”按钮,调用deleteHandler并传递{ item_id }值。

  1. deleteHander名称参数id
  2. deleteHandler调度{ item_id }作为参数的deleteBooks操作,现在命名为bookId
function Book({ title, author, item_id, category }) {
  const dispatch = useDispatch();

  const deleteHandler = (id) => { // (2) id == { item_id }
    console.log(id);
    dispatch(deleteBooks(id)); // (3)
  }

  return (
    <>
      <span>
        {title}
        </span>
        <br/>
        <span>
        {author}
      </span>
      <br/>
      <span>
        {category}
      </span>
      <br/>
      <button
        type="button"
        onClick={() => deleteHandler({ item_id })} // (1)
      >
        Remove
      </button>
    </>
  );
}
  1. deleteBooks使用bookId,并将其***直接***传递到DELETE请求URL路径和请求正文中

***此时,我认为DELETE请求在后端会失败,因为URL可能不正确,主体也不正确。***fetch只在网络错误或取消请求时抛出错误,所以我确信代码会沿着错误地继续。我相当肯定response.data只是未定义。

  1. deleteBooks分派removeBook并将bookId(仍为{ item_id })作为有效负载传递
export const deleteBooks = createAsyncThunk(
  REMOVE,
  async (bookId, thunkAPI) => {
    const response = await fetch(`${BOOK_URL}/${bookId}`,  { // (4)
      method: 'DELETE',
      body: JSON.stringify({
        item_id: bookId // (4) { item_id: { item_id } }
      }),
      headers: {
        'Content-Type': 'application/json',
      },
    });
    await thunkAPI.dispatch(removeBook(bookId)); // (5)
    return response.data;
  }
);
  1. removeBook{ item_id }作为有效负载值
export const removeBook = (book) => ({ // (6) { item_id }
  type: REMOVE,
  book, // (6) { item_id } -> action.book.item_id
});

  1. bookReducer reducer函数处理REMOVE动作,并正确访问动作有效载荷以获得嵌套的item_id属性,并过滤图书状态数组。
const bookReducer = (state = initialState, action) => {
  switch (action.type) {
    ...

    case REMOVE: 
      return state.filter((book) => book.item_id !== action.book.item_id); // (7)

    ...
  }
};

溶液

除了有效负载/参数命名问题之外,您还可以通过正确访问传递的“book”对象以获取嵌套的item_id属性来修复deleteBooks操作中的问题。
示例:

export const deleteBooks = createAsyncThunk(
  REMOVE,
  async (book, thunkAPI) => {
    const { item_id } = book // <-- destructure item_id from book object
    const response = await fetch(`${BOOK_URL}/${item_id}`,  { // <-- pass in URL path
     method: 'DELETE',
      body: JSON.stringify({ item_id }), // <-- pass in body
      headers: {
        'Content-Type': 'application/json',
      },
    });
    await thunkAPI.dispatch(removeBook(book)); // <-- pass book object
    return response.data;
  }
);

建议

在整个代码中使用一致的命名

我建议编辑所有这些函数/动作/简化器等,使代码中引用的对象名称一致,这样更容易保持和维护数据在应用中流动的心理Map。
由于Book组件仅以一个book id(即item_id prop)开始,因此传递一个“book id”值会更有意义一些。

function Book({ title, author, item_id, category }) {
  const dispatch = useDispatch();

  const deleteHandler = (id) => {
    console.log(id);
    dispatch(deleteBooks(id));
  }

  return (
    <>
      <span>
        {title}
        </span>
        <br/>
        <span>
        {author}
      </span>
      <br/>
      <span>
        {category}
      </span>
      <br/>
      <button
        type="button"
        onClick={() => deleteHandler(item_id)} // <-- pass book id
      >
        Remove
      </button>
    </>
  );
}
export const deleteBooks = createAsyncThunk(
  REMOVE,
  async (bookId, thunkAPI) => {
    const response = await fetch(`${BOOK_URL}/${bookId}`,  {
      method: 'DELETE',
        body: JSON.stringify({ item_id: bookId }),
      headers: {
        'Content-Type': 'application/json',
      },
    });
    await thunkAPI.dispatch(removeBook(bookId));
    return response.data;
  }
);
export const removeBook = (bookId) => ({
  type: REMOVE,
  bookId,
});
const bookReducer = (state = initialState, action) => {
  switch (action.type) {
    ...

    case REMOVE: 
      return state.filter(
        (book) => book.item_id !== action.bookId // <-- access book id
      );

    ...
  }
};

删除书本时检查是否成功响应

fetch响应ok * 属性,以确保DELETE请求确实成功。
示例:

export const deleteBooks = createAsyncThunk(
  REMOVE,
  async (bookId, thunkAPI) => {
    const response = await fetch(`${BOOK_URL}/${bookId}`,  {
      method: 'DELETE',
        body: JSON.stringify({ item_id: bookId }),
      headers: {
        'Content-Type': 'application/json',
      },
    });
    
    if (response.ok) {
      thunkAPI.dispatch(removeBook(bookId));
    }
    return response.data;
  }
);

***注意:**response.ok是相当标准的,但如果成功/失败的表述不同,请参阅API文档。

相关问题