我目前正在使用Material Ui的dropzone上传多个文件,想知道将文件添加/更新到redux store的最佳方法。当"onChange"触发时,我正在执行dispatch操作,该操作返回dropzone上的所有文件并将整个文件数组(具有文件对象)存储到redux状态中进行更新。
请告诉我是否有更好的处理方式。
我目前正在使用Material Ui的dropzone上传多个文件,想知道将文件添加/更新到redux store的最佳方法。当"onChange"触发时,我正在执行dispatch操作,该操作返回dropzone上的所有文件并将整个文件数组(具有文件对象)存储到redux状态中进行更新。
请告诉我是否有更好的处理方式。
我遇到类似的问题,最终使用了这个:
URL.createObjectURL(file)
blob:http://example.com/f331074d-a7f3-4972-9c37-96b490a4dd96
的URL,它只是一个字符串,可以在 img
标签的 src
属性中使用。不确定 Material Ui dropzone 返回什么,但这适用于由 <input type="file" />
返回的文件对象。TLDR: 这里解释了如何在TypeScript中使用React Context来解决问题,而不使用Redux(如果你更喜欢JavaScript,可以转换回去)。希望这不会偏离主题,因为我之前也遇到过这个问题。
在处理表单中的文件上传的特定情况下,我建议不要使用状态管理器(非序列化数据),而是使用React Context。通过这种方式,你可以将文件/文件数组(多文件上传)传递到任何需要它们的地方(当然是在提供者的范围内),而不必将props一层层地传递到所需的组件。
我确信有其他解决这个问题的方法,但是我越是使用React上下文,就越能理解其内部工作原理和与状态管理器相比的使用原则,感觉就像是一步之遥。但是让我们记住,需求范围稍有不同,因为我们想要上传一些文件并将其存储在浏览器中,甚至在发送之前进行预览,就像#jetpackpony所描述的那样,接下来的内容会很有用:DialogContextProvider.tsx
import { createContext, useMemo, useState } from 'react'
interface DialogContextValues {
attachments: File[]
setAttachments: React.Dispatch<React.SetStateAction<File[]>>
}
export const DialogContext = createContext<DialogContextValues | undefined>(undefined)
const DialogContextProvider = ({ children }: { children: JSX.Element }) => {
const [attachments, setAttachments] = useState<File[]>([])
const dialogContextValue = useMemo(
() => ({ attachments, setAttachments }),
[attachments, setAttachments],
)
return <DialogContext.Provider value={dialogContextValue}>{children}</DialogContext.Provider>
}
export default DialogContextProvider
作为组件的父级,可以获取/设置其数据。
SomeUIComponent.tsx
import DialogContextProvider from './DialogContextProvider'
export const SomeUIComponent = () => (
<div>
<h2>This is out of context</h2>
<DialogContextProvider>
<SomeComponentWhichUsesContext />
<AnotherComponentWhichUsesContext />
</DialogContextProvider>
</div>
)
此外,我们可以使用自定义钩子在代码中更加流畅地检索数据。
useDialogContext.ts
import { useContext } from 'react'
import { DialogContext } from './DialogContextProvider'
// Custom hook to access the Tone.js context
const useDialogContext = () => {
const context = useContext(DialogContext)
const attachments = context?.attachments || []
const setAttachments = context?.setAttachments || (() => [])
if (!context) {
throw new Error('useDialogContext must be used within a Dialog')
}
return { attachments, setAttachments }
}
export default useDialogContext
const { attachments, setAttachments } = useDialogContext()