无法在 api 调用期间更新状态以更改页面上的显示



我有一个名为Dashboard的页面,在这个页面上我有一个名为Dropzone的组件,用于上传文件到该页面。

当一个文件被上传时,它调用onDrop()回调,我将文件POST到我的api,然后我尝试在/api/machines/{hash}发送一个GET请求到我的api。我想在这个GET请求之前将state.pcapAnalysing变量设置为TRUE,并在它完成后将其设置为FALSE。这样做的目的是在api调用运行时在Dashboard页面上显示一条"分析"消息,这可能需要几秒钟才能返回。

由于状态没有刷新,消息没有显示,因为状态永远不会更新,显示state.pcapAnalysing为false。有人知道我怎样才能达到我想要的效果吗?本质上,我试图在api调用操作期间在Dashboard页面上显示一条消息,但这是由驻留在Dropzone.js中的组件触发的。谢谢。

Dashboard.js

...
export default function Dashboard() {
const [currentTime, setCurrentTime] = useState(0);
const [state, dispatch] = useContext(Context);
useEffect(() => {
fetch('/api/time').then(res => res.json()).then(data => {
setCurrentTime(data.time);
});
}, []);
return (
<PageBase navigation={navigation}>
<div className="flex place-content-center mt-10">
<div className="flex w-1/2 place-content-center">
{ !state.pcapUploaded ? 
state.pcapAnalysing ? 
<p>uploading</p> // Want to show this when state.pcapAnalysing is TRUE
:
<TwoCard numcols="2">
<div>
<h5 className="">Upload a PCAP file to analyse</h5>
<p>Accepted file types: .pcap, .pcapng, .tcpdump</p>
</div>
<div className="mt-5 lg:ml-2 lg:mt-0 md:mt-0">
<MyDropzone/>
</div>
</TwoCard> 
: 
<TwoCard numcols="3">
<div className='col-span-1'>
<img src={require("../Assets/pcap.png")}/>
</div>
<div className='col-span-2'>
<h5 className="">Selected File:</h5>
<p className="break-all">{state.pcapFileName}</p>
<p className="break-all">{state.pcapHash}</p>
<button type="button" onClick={clearPcap}>
Change
</button>
</div>
</TwoCard>
}
</div>
</div>
<div>
{ state.pcapUploaded ? <TileGrid tiles={tiles}/> : null } 
</div>
</PageBase>
);
}

Dropzone.js

import { useCallback, useEffect, useContext } from 'react';
import { useDropzone } from 'react-dropzone';
import { Context } from '../Helpers/Provider';

export default function MyDropzone() {
const [state, dispatch] = useContext(Context);
const onDrop = useCallback(acceptedFiles => {
const formData = new FormData();
formData.append('file', acceptedFiles[0]);
fetch('/api/upload',
{
method: 'POST',
body: formData,
}
)
.then(res => res.json())
.then(result => {
console.log('Success: ', result);
console.log("dispatching...");
dispatch({
type: 'HASH',
payload: result['hash'],
});
dispatch({
type: 'ANALYSING', // Want to use this to set state.pcapAnalysing to TRUE
});
console.log("before: " + state.pcapAnalysing);
if (state.machineIPs == null) {
console.log("Machines: ", state.pcapHash);
fetch(`/api/machines/${result['hash']}`)   // This request may take a few seconds
.then(res => res.json())
.then(data => {
console.log(data);
dispatch({
type: 'MACHINES',
payload: result,
});
});
};

dispatch({
type: 'ANALYSING', // Want to use this to set state.pcapAnalysing to false after request completes
});

console.log("after: " + state.pcapAnalysing);
})
}, [state.pcapHash])
const {getRootProps, getInputProps, isDragActive} = useDropzone({
onDrop,
maxFiles: 1,
accept: '.pcap, .pcapng, .tcpdump'
})
return (
<div {...getRootProps()} className="..<shortened>..">
Upload PCAP
<input {...getInputProps()} />
{
isDragActive ?
<p>Drop the file here ...</p> :
<p className="ml-2 mr-2">Drag 'n' drop a file here, or click to select file</p>
}
</div>
)
}

看起来应该在中设置最终状态您的/api/machines呼叫的then关闭。

所以整个调用应该是这样的:

fetch('/api/upload',
{
method: 'POST',
body: formData,
}
)
.then(res => res.json())
.then(result => {
console.log('Success: ', result);
console.log("dispatching...");
dispatch({
type: 'HASH',
payload: result['hash'],
});
dispatch({
type: 'ANALYSING', // Want to use this to set state.pcapAnalysing to TRUE
});
console.log("before: " + state.pcapAnalysing);
if (state.machineIPs == null) {
console.log("Machines: ", state.pcapHash);
fetch(`/api/machines/${result['hash']}`)   // This request may take a few seconds
.then(res => res.json())
.then(data => {
console.log(data);
dispatch({
type: 'ANALYSING', // Want to use this to set state.pcapAnalysing to false after request completes
});
dispatch({
type: 'MACHINES',
payload: result,
});
});
};
})
}, [state.pcapHash])

注意,我把这一行都去掉了

console.log("after: " + state.pcapAnalysing);

因为即使我将它移动到thenclose中,状态也不会被更新,因为组件重新渲染还没有发生。

最新更新