如何让 React 在 POST 或 DELETE 到数据库后从 API 重新获取我的数据?

How to get React to re fetch my data from API after a POST or DELETE to Database?

新手反应,如果能帮助我的组件在 POST 或 DELETE 后重新呈现数据,我将不胜感激。数据在 post 上一直流到我的数据库并删除,但是我必须手动重新加载页面才能更新显示

DELETE - 从 useFetch 自定义挂钩传入的状态 [data,setData]

function BookList({ data, isPending, setData }) {
 

    if (isPending){
        return <p>Data Loading!</p>
    }
   

    const handleDelete = (book_id) => {
        fetch(`http://localhost:3000/books/${book_id}`, {
            method: 'DELETE'
        })
        .then(response => response.json())
        .then(()=> {
            const updatedBooks = data.data.filter(item => item.book_id !== book_id)
            setData(updatedBooks)
           
        })

    }
   
  const rows = data.data.map(({book_id, book_title, author}, index) => (
    <tr>
        <td>{book_id}
        </td>
        <td>{book_title}</td>
        <td>{author}</td>
        <button onClick={()=> handleDelete(book_id)}>Delete</button>

    
    </tr>
  ))

  return (
    <div>
      <table>
        <thead>
          <tr>
            <th>Id</th>
            <th>Title</th>
            <th>Author</th>
            <th>Delete</th>
          </tr>
        </thead>
        <tbody>{rows}
        </tbody>
      </table>
    </div>
  );
}

export default BookList;

和POST

import { useState } from "react";

function NewBook({data, setData}) {
  const initialFormState = {
    book_title: "",
    author: ""
  };

  const [formData, setFormData] = useState({ ...initialFormState });

  const handleChange = ({ target }) => {
    setFormData({ ...formData, [target.name]: target.value });
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    const newBook = formData;
    console.log(newBook);
    const url = "http://localhost:3000/books";
    const requestOptions = {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(newBook),
    };
    fetch(url, requestOptions)
      .then((response) => console.log("Submitted Successfully"))
      .then(()=> {setData.push(formData)})
      .catch((error) => console.log("Form submit error", error));

    setFormData({ ...initialFormState });
   
  };

我认为您应该使用 state management 工具,例如 react reduxprovider 来访问应用程序周围的全局状态。我个人比较喜欢 provider. however, redux 有它自己的优点。选择状态管理方法后,您可以定义一个函数来调用 API 每当用户在特定页面等上进行交互时

有很多方法可以根据需要管理状态。你需要选择你需要的。我将从最简单的方法开始处理您的情况,

1.提升状态

因为你有不同的相关组件,它们各自处理一些改变状态的操作。状态提升意味着,您将所有状态移动到父组件并传递子组件所需的 props [属性或事件]。

在您的情况下,您将有一个父组件,您将在其中获取数据,而您的 BookListNewBook 组件将是它的子组件。您会将删除逻辑移至父级并将函数传递给 BookList 作为道具以在那里调用。

现在,当您 Add/Remove 时,您可以在父级中使用完整的图书清单。您可以删除一本书并根据状态从您的列表中删除该项目或对您的列表进行乐观更新。

乐观更新意味着,您立即更新您的列表,然后根据delete/add处理列表的状态。

2。上下文 API

此时您需要与您的应用程序全局共享一些数据,例如主题数据或授权数据等。您可以使用上下文来处理您的情况,将上下文提供程序与 BookList 的共同父级包装在一起或 NewBook。在你的情况下解除状态很容易。

3。全局状态管理器

如果你想在中央位置管理你的状态,你可以使用一些状态管理工具,比如 Redux 或 Mobx。如果您的应用程序具有一定程度的复杂性来管理状态,那么这是最好的方法之一。设置 redux 有点吓人,但值得努力。

考虑使用上面答案中指出的全局状态管理。我建议使用 react 的 context API,因为它对初学者很友好,并且可以很好地为这样一个小项目服务。 Context API docs

您的上下文提供程序文件可能是这样的

import { createContext, useContext, useState } from "react";

const BooksContext = createContext();

export function useBooks() {
  return useContext(BooksContext);
}

export function BooksContextProvier({ children }) {
  const [bookList, setBookList] = useState([]);
  const [loading, setLoading] = useState(false);

  const value = {
    bookList,
    loading,
    setBookList,
    setLoading,
  };

  return (
    <BooksContext.Provider value={value}>{children}</BooksContext.Provider>
  );
}

确保在 App.js 中引入您的上下文,并像这样

将其包裹在您的组件周围
return (
    <BooksContextProvier>
        <NewBook />
        <BookList />
    </BooksContextProvier>
)

在 NewBook 中,从上下文中引入 bookList 和 setBookList 函数,这样您在组件中所做的任何更改都会在全局反映出来。因此,您不想在 handleSubmit 结束时再次调用 setFormData,而是希望 setBookList 并包含新书。所以你的 NewBook 组件的代码将是这样的

  function NewBook() {
    const initialFormState = {
      book_title: "",
      author: ""
    };
  
    const [formData, setFormData] = useState({ ...initialFormState });
    const {bookList, setBookList} = useBooks()
  
    const handleChange = ({ target }) => {
      setFormData({ ...formData, [target.name]: target.value });
    };
  
    const handleSubmit = (event) => {
      event.preventDefault();
      const newBook = formData;
      console.log(newBook);
      const url = "http://localhost:3000/books";
      const requestOptions = {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(newBook),
      };
      fetch(url, requestOptions)
        .then((response) => console.log("Submitted Successfully"))
        .catch((error) => console.log("Form submit error", error));
  
      setBookList([formData, ...bookList])
     
    };
}

对于您的 BookList 组件,您可以合并以下代码以利用上下文

function BookList() {
    const {bookList, setBookList} = useBooks()
 
    if (loading){
        return <p>Data Loading!</p>
    }
   

    const handleDelete = (book_id) => {
        fetch(`http://localhost:3000/books/${book_id}`, {
            method: 'DELETE'
        })
        .then(response => response.json())
        .then(()=> {
            const updatedBooks = data.data.filter(item => item.book_id !== book_id)
            setBookList(updatedBooks)
        })

    }

您也可以在全局级别修改和使用加载状态,我没有将其包含在示例代码中,但您可以将其拉入您的组件并像操作 bookList 一样操作它。