更新数据库后重新渲染
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?更容易调试。
我有一个组件,我在其中从 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?更容易调试。