setDropzoneFiles
is done, then I need to execute setDropzoneIsLoading
. In react class, I can assign callback to setState(), how do I achieve the same with the following code?
const Dropzone = () => {
const [dropzoneFiles, setDropzoneFiles] = useState([]);
const [dropzoneIsLoading, setDropzoneIsLoading] = useState(false);
const onDropAccepted = useCallback(
acceptedFiles => {
let someFiles = ['a', 'b'];
// How to use callback?
setDropzoneFiles(someFiles, () => {
setDropzoneIsLoading(true)
})
}
);
const {getRootProps, getInputProps} = useDropzone({
onDropAccepted,
onDropRejected,
multiple: true
});
}
export default Dropzone;
setDropzoneFiles
is done, then I need to execute setDropzoneIsLoading
. In react class, I can assign callback to setState(), how do I achieve the same with the following code?
const Dropzone = () => {
const [dropzoneFiles, setDropzoneFiles] = useState([]);
const [dropzoneIsLoading, setDropzoneIsLoading] = useState(false);
const onDropAccepted = useCallback(
acceptedFiles => {
let someFiles = ['a', 'b'];
// How to use callback?
setDropzoneFiles(someFiles, () => {
setDropzoneIsLoading(true)
})
}
);
const {getRootProps, getInputProps} = useDropzone({
onDropAccepted,
onDropRejected,
multiple: true
});
}
export default Dropzone;
Share
Improve this question
asked Sep 21, 2019 at 2:02
kenpeterkenpeter
8,30415 gold badges75 silver badges105 bronze badges
2
- Callabck in setState hook is removed, instead you need to use useEffect with dependency array and initial state condition. – ravibagul91 Commented Sep 21, 2019 at 2:48
-
Have you considered to use useEffect instead for the loading effect instead of
setDropzoneIsLoading(true)
? – Koala Yeung Commented Sep 21, 2019 at 3:42
2 Answers
Reset to default 4The answers you will find online will point you to using useEffect
, but this is simply a coverup for a bigger underlying issue.
As mentioned in this post by Lenz Weber as to why there is no callback in useState()
:
Because it invokes a thought pattern that may very well be an antipattern with hooks.
With hooks, you are writing code more declarative than imparative.
I remend reading the whole thread as there is great insight in the discussion.
What to do instead?
If you use Redux's useReducer
and dispatch: through a Reducer, you can, in one operation, set the dropZoneFiles and isLoading to true without being interrupted in the middle.
A lot of folks are not fond of Redux, but it exists precisely for this kind of situation.
Also, Dan Abramov from Facebook (big promoter of hooks) himself has frequently mentioned (here for example) that not every ponent should be immediately migrated to hooks, especially because best-practices need to solidify; I myself prefer Class Components when dealing with plex ponents.
You can use the useEffect hook:
const Dropzone = () => {
const [dropzoneFiles, setDropzoneFiles] = useState([]);
const [dropzoneIsLoading, setDropzoneIsLoading] = useState(false);
const onDropAccepted = useCallback(
acceptedFiles => {
let someFiles = ['a', 'b'];
// How to use callback?
setDropzoneFiles(someFiles);
}
);
useEffect(() => {
if (dropzoneFiles) {
setDropzoneIsLoading(true);
}
}, [dropzoneFiles])
const {getRootProps, getInputProps} = useDropzone({
onDropAccepted,
onDropRejected,
multiple: true
});
}
export default Dropzone;