Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added resetOnChange property and custom handler #27

Merged
merged 3 commits into from
Apr 5, 2021

Conversation

arnautov-anton
Copy link
Collaborator

Added resetOnChange property to both upload buttons so when user deletes file from preview and then decides to upload that same file again, they can. This thing has been already (partially) implemented in FileUploadButton with reference to input element so I decided to rewrite it a bit and add it to ImageUploadButton as well.

Here's the preview of the "bug":

Screen.Recording.2021-04-02.at.2.20.06.PM.mov

Copy link

@ath92 ath92 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. From what I understand, setting the value to true is what fixes the issue for you, right? Would it make sense to set the default to true?

inputRef.current.blur();
}
}}
onChange={handleFileChange(handleFiles, resetOnChange)}
Copy link
Contributor

@vishalnarkhede vishalnarkhede Apr 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
onChange={handleFileChange(handleFiles, resetOnChange)}
onChange={() => handleFileChange(handleFiles, resetOnChange)}

You sure this is correct? You are calling the function on every render ... not on change

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, handleFileChange is just a closure that takes into consideration actual user handler (in this case handleFiles) and resetOnChange property and returns function that handles onChange event. I could memoize it if you think it'd have impact on performance.

Copy link
Contributor

@vishalnarkhede vishalnarkhede Apr 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh ok, I missed the part where you return the function from handleFileChange, my bad. Memoization is not necessary. But handleFileChange doesn't exactly handle the file-change-event (which I assumed it would). It only gives you handler. You can consider following change, which avoids calling that function on every render and does exactly what it says:

// utils.js
export const handleFileChange = (
  files: WhateverType,
  resetOnChange: boolean = false,
  handler?: (files: Array<File>) => void, // last since its optional
) => {
  if (!files) return;

  try {
    handler?.(Array.from(files));
  } catch (error) {
    console.error(error);
  }

  if (resetOnChange) currentTarget.value = '';
};

// And in FileUploadButton.tsx and ImageUploadButton.tsx
const onFileChange = ({ currentTarget }: React.ChangeEvent<HTMLInputElement>) => {
  const updatedFiles = currentTarget.files;
  handleFileChange(updatedFiles, resetOnChange, handleFiles);
}

<input
  ...
  onChange={onFileChange}
/>

Copy link
Collaborator Author

@arnautov-anton arnautov-anton Apr 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see where you're coming from and I'm sorry for confusing function naming. As for your snippet - it makes sense - but I'll go for a hook to make it more React-y and so you wouldn't have to define that function twice.

// utils.ts
export const useHandleFileChangeWrapper = (
  resetOnChange: boolean = false,
  handler?: (files: Array<File>) => void,
) =>
  useCallback(
    ({ currentTarget }: React.ChangeEvent<HTMLInputElement>) => {
      const { files } = currentTarget;

      if (!files) return;

      try {
        handler?.(Array.from(files));
      } catch (error) {
        console.error(error);
      }

      if (resetOnChange) currentTarget.value = '';
    },
    [callback, resetOnChange],
  );

// in <File/Image>UploadButton.tsx then:
const onFileChange = useHandleFileChangeWrapper(resetOnChange, handleFiles);

<input onChange={onFileChange} />;

This way - no more unwanted renders and naming is clear (at least I think that it's pretty clear). 😄

@arnautov-anton
Copy link
Collaborator Author

Looks good. From what I understand, setting the value to true is what fixes the issue for you, right? Would it make sense to set the default to true?

Right! Not sure about the default value though. Could be possibly a breaking change if set to true.

@ath92
Copy link

ath92 commented Apr 4, 2021

Looks good. From what I understand, setting the value to true is what fixes the issue for you, right? Would it make sense to set the default to true?

Right! Not sure about the default value though. Could be possibly a breaking change if set to true.

Okay, but wasn't this default behaviour for FileUploadButton before? So defaulting to false would be the breaking change for that component?

@arnautov-anton
Copy link
Collaborator Author

Looks good. From what I understand, setting the value to true is what fixes the issue for you, right? Would it make sense to set the default to true?

Right! Not sure about the default value though. Could be possibly a breaking change if set to true.

Okay, but wasn't this default behaviour for FileUploadButton before? So defaulting to false would be the breaking change for that component?

Actualy... that's true. Now what's lesser evil?

@ath92
Copy link

ath92 commented Apr 4, 2021

Looks good. From what I understand, setting the value to true is what fixes the issue for you, right? Would it make sense to set the default to true?

Right! Not sure about the default value though. Could be possibly a breaking change if set to true.

Okay, but wasn't this default behaviour for FileUploadButton before? So defaulting to false would be the breaking change for that component?

Actualy... that's true. Now what's lesser evil?

Maybe just set it to true for files and false for images? Although IMO your changes just feel like a bug fix rather than something that really needs to be a separate prop. Not something I feel very strongly about though.

@arnautov-anton
Copy link
Collaborator Author

Looks good. From what I understand, setting the value to true is what fixes the issue for you, right? Would it make sense to set the default to true?

Right! Not sure about the default value though. Could be possibly a breaking change if set to true.

Okay, but wasn't this default behaviour for FileUploadButton before? So defaulting to false would be the breaking change for that component?

Actualy... that's true. Now what's lesser evil?

Maybe just set it to true for files and false for images? Although IMO your changes just feel like a bug fix rather than something that really needs to be a separate prop. Not something I feel very strongly about though.

I'll go for the "true for files and false for images" to preserve default behaviour in case somebody would want to go that way.

Copy link
Contributor

@vishalnarkhede vishalnarkhede left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend removing useCallback. It doesn't sound effective in this case!!

@DanC5 DanC5 merged commit 69a62e1 into GetStream:master Apr 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants