Jaaneek / useFilePicker

Simple react hook to open browser file selector.

Home Page:https://use-file-picker.vercel.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Just need onChange

fabpico opened this issue · comments

I need more control over the state of the chosen files. I already had this situation #26 and fixed it also with useEffect.

    const [openFileSelector, {filesContent}] = useFilePicker({
        accept: props.fileEndings,
        multiple: Boolean(props.multiple),
        readAs: 'DataURL',
    });

    useEffect(() => {
        props.onChange(filesContent)
    }, [filesContent])

But now I want to repopulate a file selection in an edit form. But useEffect will overwrite anything with an empty filesContent due to its initializaiton.

Can there not just be an onChange within useFilePicker to use?

What do you mean by "repopulate a file selection"? Do you want to keep the previous selection or just avoid the onChange invocation with empty array? Here are some solutions:

  • for keeping previous selection: #51 (comment)
  • If you want to avoid the initialization step, then just add an if statement to your useEffect:
useEffect(() => {
  if (filesContent.length) {
    props.onChange(filesContent)
  }
}, [filesContent])

With that check, your onChange won't be called without actual content.

Can there not just be an onChange within useFilePicker to use?

We believe it's not needed. You can read more about reasons here: #32 (comment)

What do you mean by "repopulate a file selection"?

An edit form of an entity is usually prefilled/repopulated with the entity's data fetched from the database. One form field of my entity is for attachments, which I use useFilePicker.

Below the file picker I display the attachments fetched from the database (repopulation). But the attachments to display are being overwritten with an empty array, because of that useEffect which I use, to show the chosen Items after selection.

for keeping previous selection: #51 (comment)

This would still overwrite my repopulated items with an empty array, because filesContent is empty on initialization.

If you want to avoid the initialization step, then just add an if statement to your useEffect:

Yes I already figured that out as a workaround. But I find this is a hand brake and not a clean solution.

We believe it's not needed.

I do not agree. Intuitively I expect an onChange like in any other form field, or any other open source react component which I know, where you can change something interactively. And fact is, currently I need to implement a hand brake inside useEffect to imitate an onChange.

Ok, we'll talk through it within the maintainers team. Thanks for the suggestion.

It is also worth noting that we're currently in the process of changing the openFileSelector function to return a promise with all the values returned from the hook, which was suggested here #56 and is currently in code review #58. We'll be releasing version 1.6.0 with that feature soon, so maybe you can use it before we implement onChange.

Turns out that we weren't able to reliably introduce promise to useFilePicker due to browser APIs, more explanation can be found here: #58 (comment)
Because of that, we decided to implement onChange handlers like you suggested @fabpico.
There is already a PR for this: #60 and we're aiming to bring this feature in the next release 1.6.0.

Thanks for your input @fabpico!

We had to do quick bump to 1.6.1, let us know if we can close this issue once you test it out @fabpico

@Jaaneek How to use it?

@fabpico just pass handlers as props to the hook.
There are 3 functions you can use, which are described in the docs:
image

example:

const [openFilePicker] = useFilePicker({
   onFilesSelected: (data) => { 
      // your logic whenever user submits valid or invalid files
   },
})

Works so far 👍 . Thanks for the quick feedback and improvement.