更新数据库后重新渲染

Re Render After Updating DB

我有一个组件,我在其中从 API 获取数据并将其显示在屏幕上:

const RestaurantsList = () => {
  const [restaurants, setRestaurants] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch("http://localhost:3001/api/v1/restaurants");
      const data = await response.json();
      //console.log(data);
      setRestaurants(data);
    };
    fetchData();
  }, []);
...

我有另一个组件 AddRestaurant,我在其中向 API 发出 Post 请求以添加新餐厅:

const AddRestaurant = () => {
  const [name, setName] = useState("");
  const [location, setLocation] = useState("");
  const [priceRange, setPriceRange] = useState("");

  function nameUpdate(e) {
    setName(e.target.value);
  }
  function locationUpdate(e) {
    setLocation(e.target.value);
  }

  const handleSubmit = async function (e) {
    //e.preventDefault();

    try {
      await fetch("http://localhost:3001/api/v1/restaurants", {
        method: "POST",
        made: "cors",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          name,
          location,
          price_range: priceRange,
        }),
      });
    } catch (err) {
      console.log(err);
    }
    setName("");
    setLocation("");
    setPriceRange("");
  };
...

问题是,当我添加新餐厅时,我想在不刷新页面的情况下添加列表。如果我在 useEffect 上添加 [restaurants] 依赖项,它会一直循环发出 GET 请求。

两个组件都是此组件的子组件:

const Home = () => {
  return (
    <div>
      <Header />
      <AddRestaurant />
      <RestaurantsList />
    </div>
  );
};

export default Home;

最好的解决方案是什么?

已更新

它适用于安德烈的解决方案,但现在我想在删除餐厅时做同样的事情。我应用了相同的方法,但不起作用:

<button
                    className="btn btn-danger"
                    onClick={(e) => onDelete(res.id, e)}
                  >
                    Delete
                  </button>



const onDelete = async (id, e) => {
    e.preventDefault();
    try {
      await fetch(`http://localhost:3001/api/v1/restaurants/${id}`, {
        method: "DELETE",
      });
    } catch (err) {
      console.log(err);
    }
    setFetchRestaurants(true);
  };

onDelete 按钮和函数在 RestaurantList 组件上。

一个解决方案是添加一个以 true 开始并获取初始数据的顶级状态。当数据获取完成时,我们将其设置为 false

const Home = () => {
  const [fetchRestaurants, setFetchRestaurants] = useState(true)

  return (
    <div>
      <Header />
      <AddRestaurant setFetchRestaurants={setFetchRestaurants} />
      <RestaurantsList fetchRestaurants={fetchRestaurants} setFetchRestaurants={setFetchRestaurants} />
    </div>
  )
}

export default Home
const RestaurantsList = ({ fetchRestaurants, setFetchRestaurants }) => {
  const [restaurants, setRestaurants] = useState([])

  useEffect(() => {
    if (fetchRestaurants) {
      const fetchData = async () => {
        const response = await fetch('http://localhost:3001/api/v1/restaurants')
        const data = await response.json()
        // console.log(data);
        setRestaurants(data)
      }
      fetchData()
      setFetchRestaurants(false)
    }
  }, [fetchRestaurants, setFetchRestaurants])

  // ...
}

然后在 AddRestaurant:

const handleSubmit = async function (e) {
  // ...
  setFetchRestaurants(true)
  setName('')
  setLocation('')
  setPriceRange('')
}

fetchRestaurants 发生变化时,RestaurantsList 将重新渲染并获取新数据。

RTK 查询 是一个为您完成大量此类工作的库,请在此处查看文档:

我们应该使用一个变量来通知组件有关新更新的信息。
我建议做这样的事情。

export default function Home () {
  const [
    timeOfLastRestaurantCreation,
    setTimeOfLastRestaurantCreation
  ] = useState<string>()

  return (
    <div>
      <Header />
      <AddRestaurant
        onAddRestaurant={() => {
          setTimeOfLastRestaurantCreation(new Date().toISOString())
        }}
      />
      <RestaurantsList
        timeOfLastRestaurantCreation={timeOfLastRestaurantCreation} 
      />
    </div>
  )
}

PS。为什么用 ISOString 而不是 Date?更容易调试。