我有一个具有两个功能的 React 组件:一个用于获取数据 (
getData
),一个用于发送数据 (sendData
)。单击按钮时,我希望发生以下情况:如果之前未调用过 getData
,则应首先调用 getData
,然后调用 sendData
。如果之前已经调用过getData
,则应直接调用sendData
。
这是我构建的结构:
import { useState } from "react";
export function App() {
const [data, setData] = useState(null);
const getData = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos');
const result = await response.json();
setData(result);
}
const sendData = () => {
console.log(data);
// data sending operations
}
const handleClick = async () => {
if (!data) {
await getData();
}
sendData();
}
return (
<button onClick={handleClick}>Click me!</button>
);
}
您可以在这个 React Playground 中看到代码(因为这里的代码片段不支持某些功能,例如 fetch)。
问题是:
sendData
在getData
完成后立即被调用,并且由于我们的状态(data
)尚未更新,所以sendData
看不到当前状态。
当然,我想到的第一个解决方案是让
getData
返回数据,并将返回的数据作为参数传递给sendData
。但如果由于某种原因我们不想这样做,我们可以找到其他解决方案吗?我想过使用useEffect
,但是我不需要在状态更新时调用sendData
。我只需要在按下按钮时调用它。
你可以做这样的事情 -
import { useState } from "react";
export function App() {
const [data, setData] = useState(null);
const getData = async (sendData) => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/');
const result = await response.json();
setData(result);
if (sendData) sendData(result);
}
const sendData = (result = data) => {
console.log(result);
//data sending operations
}
const handleClick = async () => {
if (!data) await getData(sendData);
}
return (
<button onClick={handleClick}>Click me!</button>
);
}
将 sendData 作为回调传递给 getData 函数。如果通过,它将调用 sendData 并传递最新的 API 结果,否则它将从状态变量中获取。
您也可以将其写为-
import { useState } from "react";
export function App() {
const [data, setData] = useState(null);
const getData = async (allowSendingData) => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/');
const result = await response.json();
setData(result);
if (allowSendingData) sendData(result);
}
const sendData = (result = data) => {
console.log(result);
//data sending operations
}
const handleClick = async () => {
if (!data) await getData(true);
}
return (
<button onClick={handleClick}>Click me!</button>
);
}
这里没有传递回调,而是传递一个布尔值并根据条件直接调用sendData。