我有一个下载对话框,你可以点击下载图形在我的网站上。因为图形是用HTML画布创建的,所以我不能简单地下载图像链接数组。我必须联系每个组件,并将每个组件呈现为一个数据URI。
在我的应用程序组件上,我定义了一个上下文来跟踪应该下载哪些组件。
export const DownloadFlagsContext = React.createContext<any>(null)
const App: React.FunctionComponent = (props) => {
const [downloadFlags, setDownloadFlags] = useState([])
return (
<DownloadFlagsContext.Provider value={{downloadFlags, setDownloadFlags}}>
<DownloadDialog/>
<div className="graphics">
<Graphic id={1}>
<Graphic id={2}>
<Graphic id={3}>
(multiple graphics)
</div>
</DownloadFlagsContext.Provider>
)
}
在我的DownloadDialog中,我通过将downloadFlags设置为每个需要呈现的组件的id来触发下载。
const download = () => {
const newDownloadFlags = [] as any
for (let i = start; i < end; i++) {
newDownloadFlags.push(i)
}
setDownloadFlags(newDownloadFlags)
}
现在,在每个图形组件中,如果downloadFlags被更改并包含它的id,我将触发下载。
const render = () => {
const canvas = document.createElement("canvas")
/* code to render the graphic */
return canvas.toDataURL("image/png")
}
useEffect(() => {
if (downloadFlags.includes(props.id)) {
download("filename", render())
setDownloadFlags(downloadFlags.filter((s: string) => s !== props.id))
}
}, [downloadFlags])
问题是这段代码触发了
下载。例如,如果我将下载设置为6张图形,它将导致下载21幅图像,因为每次更改downloadFlags时,所有组件都将被重新呈现,不同之处在于它包含少一个id。因此,总共将下载6+5+4+3+2+1图像。显然,这是非常糟糕的,如果我有很多图形可下载。
我想防止组件重新呈现,以便它只下载前6次。
另外,我不想使用服务器。我想下载客户端的图片。
发布于 2022-03-21 18:14:46
我已经想出了解决办法。在我的app组件中,我跟踪下载ID以及启用下载的布尔标志:
export const DownloadIDsContext = React.createContext<any>(null)
export const DownloadFlagContext = React.createContext<any>(null)
const App: React.FunctionComponent = (props) => {
const [downloadIDs, setDownloadIDs] = useState([])
const [downloadFlag, setDownloadFlag] = useState(false)
return (
<DownloadFlagContext.Provider value={{downloadFlag, setDownloadFlag}}>
<DownloadURLsContext.Provider value={{downloadURLs, setDownloadURLs}}>
<DownloadDialog/>
<div className="graphics">
<Graphic id={1}>
<Graphic id={2}>
<Graphic id={3}>
(multiple graphics)
</div>
</DownloadURLsContext.Provider>
</DownloadFlagContext.Provider>
)
}
在我的DownloadDialog中,我在启动下载时将布尔标志设置为true。
const download = () => {
const newDownloadIDs = [] as any
for (let i = start; i < end; i++) {
newDownloadIDs.push(i)
}
setDownloadIDs(newDownloadIDs)
setDownloadFlag(true)
}
现在,我只检查布尔标志,而不是检查子组件中的下载ID数组。由于它被立即设置为false,它实际上只导致组件呈现一次。
useEffect(() => {
if (downloadFlag) {
if (downloadIDs.includes(props.id)) {
download("filename", render())
setDownloadIDs(downloadIDs.filter((s: string) => s !== props.id))
setDownloadFlag(false)
}
}
}, [downloadFlag])
https://stackoverflow.com/questions/71561920
复制相似问题