[Question] Updating atom from async loop #1723
-
Hello, I've been fiddling with Recoil and my testing application and stuck with a bit of functionality. I hope you can clarify what's happening and how to approach this. So... I'm basically building custom files uploader and I want it to respond to each individual file being uploaded by showing something like '12 of 38 files uploaded". What do I have: const filesAtom = atom({
key: 'files',
default: [{
file: File,
isDone: bool,
...
}],
}); Now, apart from some atoms to track UI states there is an async function that uses async function createFile(file: File) {
...
returns Promise<string>
} createFile returns an async function uploadFile({ file, uploadLink, onProgressFn, onFinishFn }) {
return new Promise( resolve ) => {
const upload = new tus.Upload(file, {
...
//request config,
onError: function (error) {
//handle error
},
onProgress: function () {
//calc the progress %
onProgressFn(progress) // which is an Atom Progress setter
},
onSuccess: function () {
...
resolve(filename); //here I wanted to return the filename to update filesAtom (change file isDone state to true)
},
});
// Start the upload
upload.start();
});
} async function handleUploadFiles({ files, onProgressFn, onFinishFn }) {
for await (const fileObj of files) {
const uploadingLink= await createFile(fileObj.file);
const filename = await uploadFile({
file: fileObj.file,
uploadLink: uploadingLink,
onProgressFn: onProgressFn,
onFinishFn: onFinishFn,
});
//use file name from the Promise above to make a new files[] and set it with setFiles
//doesnt work like that
}
} and then I run this from my component function MyComponent() {
const [files, setFiles] = useRecoilState(filesAtom);
const [progress, setProgress] = useRecoilValue(progressAtom);
...
handleUploadFiles({ files , setProgress , setFiles});
return (...)
} So, loading bar is updated while each file is being loaded by passing progress setter all the way to Would appreciate any ideas about it, thanks. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
But I would reconsider the model of atoms and store the whole upload (promise) in an atom, so there's no |
Beta Was this translation helpful? Give feedback.
-
Turns out to be such a simple solution, great, that works. Thanks for advice |
Beta Was this translation helpful? Give feedback.
useRecoilState
(and all other hooks/fns where you can set state) accepts updater fn(state) => state
where you get latest state with all the changes applied - not the state used in current render. Basically the interface and usage is the same asuseState
from react.But I would reconsider the model of atoms and store the whole upload (promise) in an atom, so there's no
isDone
flag etc.