我有一个名为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);
因为即使我将它移动到then
close中,状态也不会被更新,因为组件重新渲染还没有发生。