Skip to content
This repository has been archived by the owner on Jan 14, 2021. It is now read-only.

RHFInput + Semantic UI Select / Checkbox #21

Closed
njuro opened this issue Dec 5, 2019 · 52 comments
Closed

RHFInput + Semantic UI Select / Checkbox #21

njuro opened this issue Dec 5, 2019 · 52 comments
Labels
question Further information is requested

Comments

@njuro
Copy link

njuro commented Dec 5, 2019

Hello, first of all thanks for your effort creating this library.

Today I have been trying to integrate RHF with components from Semantic UI react library. RHFInput works fine with Form.Input (basic text field), but it fails when I try to wrap Form.Select (https://react.semantic-ui.com/addons/select/) or Form.Checkbox (https://react.semantic-ui.com/modules/checkbox/) with it. I think the reason for this is that Form.Select is not implemented with traditional <select> html element, but rather with some <div> magic and Form.Checkbox also generates some strange "hidden" <input type="checkbox"> element. I believe Semantic UI is fairly popular and used library, so I think it might be worthy to look into this, thank you! Here is the simplified code I am using, nothing is sent when the form is submitted:

<Form onSubmit={handleSubmit(onSubmit)}>
  <RHFInput
    name="color"
    as={
      <Form.Select
        label="Pick a color"
        options={colors}
        required
      />
    }
    register={register}
    setValue={setValue}
  />
  <RHFInput
    name="tos"
    as={<Form.Checkbox label="Accept TOS" />}
    type="checkbox"
    register={register}
    setValue={setValue}
  />
  <Form.Button fluid>Submit</Form.Button>
</Form>

EDIT:

The checkbox generates following error: _options$0$ref.attributes is undefined and also warning Warning: Failed prop type: Invalid prop valuesupplied toCheckbox`.

And the select generates no error, but the value after submitting is always undefined.

@njuro njuro changed the title RHFInput + Semantic UI Select / RHFInput + Semantic UI Select / Checkbox Dec 5, 2019
@JeromeDeLeon
Copy link
Contributor

Can you generate a codesandbox for this one? Thanks.

@JeromeDeLeon JeromeDeLeon added the question Further information is requested label Dec 7, 2019
@bluebill1049
Copy link
Member

@njuro are you using the latest version?

@JeromeDeLeon
Copy link
Contributor

I replicated your issue and led me to react-hook-form using my build though.

@njuro
Copy link
Author

njuro commented Dec 8, 2019

Here is the CSB: https://codesandbox.io/s/suspicious-frog-75c77

RHF is aware of the fields, but they are always undefined.

Looks like react-hook-form-input version 1.1.5 solved the error thrown by checkbox, but the value is still not there

@raymond-ong
Copy link

I think I am encountering the same issue with Semantic UI Dropdown.
Also, notice from @njuro 's CSB, you need to click the checkbox 2 times for it to get ticked.
For the Dropdown case, nothing happens the first time the user selects something. Only the second attempt selects something from the Dropdown.
Regardless, I'm getting "undefined" inside the submit function.
Please advice. Thank you!

@bluebill1049
Copy link
Member

Thanks I will investigate the issue soon, in the meantime you could leverage custom register at useffect. React hook from input just some sugar syntax on top. Oh and please provide a codesandbox if u can.

@JeromeDeLeon
Copy link
Contributor

JeromeDeLeon commented Dec 9, 2019

I think the problem lies in how we get the value from onChange and onBlur event because SUI passes the value to second param onChange(e, props) like so that's why data is always undefined because it only checked the e where the value is in the second param or maybe we can move that in state. Plus, invalid prop "value"... is showing when passing value that doesn't conform to their types (string or number).

@JeromeDeLeon
Copy link
Contributor

JeromeDeLeon commented Dec 9, 2019

I can think of two solutions (maybe @bluebill1049 has better idea):

  1. Lift the state up and let the user pass the data:
// outside RHFI component
const handleChange = (e, { checked }) => {
  return checked;
}

// inside RHFI component
const handleChange = async (...args) => {
  // onChange here is the prop to lift
  const data = await onChange(args);
  setValue(name, data, isOnChange);

  // we can remove this
  if (onChange) {
    onChange(e);
  }
};
  1. We accept second param to accomodate SUI like what @bluebill1049 did in react-select
const handleChange = (e, props) => {
  const data = commonTask(e && e.target ? e.target : isSUI ? props : e);
  setValue(name, data, isOnChange);
  if (onChange) {
    onChange(e);
  }
};

@bluebill1049
Copy link
Member

thanks @JeromeDeLeon why not use onChangeEvent ? there is an example in readme for react native.

@JeromeDeLeon
Copy link
Contributor

Oh! Thanks! @bluebill1049 I forgot that one.

@JeromeDeLeon
Copy link
Contributor

Can we not make it asynchronous?

@JeromeDeLeon
Copy link
Contributor

@njuro and @raymond-ong , I'l try to provide an example for this and let you know guys.

@bluebill1049
Copy link
Member

Can we not make it asynchronous?

what do you mean?

@JeromeDeLeon
Copy link
Contributor

JeromeDeLeon commented Dec 10, 2019

await event(args) something like this?

@bluebill1049
Copy link
Member

hmm then you need async right?

@bluebill1049
Copy link
Member

and it will always return promise and resolve

@JeromeDeLeon
Copy link
Contributor

Yes we can await that one.

@JeromeDeLeon
Copy link
Contributor

Anyway this is beyond the scope of the issue. we'll move this discussion in the spectrum.

@bluebill1049
Copy link
Member

sounds good

@njuro
Copy link
Author

njuro commented Dec 10, 2019

@JeromeDeLeon @bluebill1049 Thanks for the hints guys, I think I figured it out: https://codesandbox.io/s/dazzling-napier-ne3e6

@raymond-ong hope it will solve your issue too

@bluebill1049
Copy link
Member

awesome @njuro! that's what i referred above.

@njuro
Copy link
Author

njuro commented Dec 10, 2019

Thanks @bluebill1049 , the last thing that annoys me is the
Warning: Failed prop type: Invalid prop 'value' supplied to 'Checkbox', which shows when the page is loaded, but does not seem to affect functionality.

@bluebill1049
Copy link
Member

we should fix it, do you have a codesandbox for it? let's patch it.

@JeromeDeLeon
Copy link
Contributor

@njuro , I mentioned that case above. Sorry, I wasn't able to follow up the example.

@JeromeDeLeon
Copy link
Contributor

JeromeDeLeon commented Dec 10, 2019

@njuro You can solve it by passing value as string like tos or isTos

@raymond-ong
Copy link

@JeromeDeLeon @bluebill1049 Thanks for the hints guys, I think I figured it out: https://codesandbox.io/s/dazzling-napier-ne3e6

@raymond-ong hope it will solve your issue too

Thanks @njuro for the codesandbox and @bluebill1049 for the onChangeEvent suggestion!
Will give it a try tomorrow :-)

@bluebill1049
Copy link
Member

@raymond-ong no worries 👍 guys

@njuro
Copy link
Author

njuro commented Dec 10, 2019

Thanks @JeromeDeLeon now it works perfectly. I already created a little library in my project which wraps Semantic UI form components in RHFInput so I can work with it seamlessly, might publish it as a package once I polish it.

@bluebill1049
Copy link
Member

closing this issue for now :) we can keep the conversation in here :)

@njuro
Copy link
Author

njuro commented Dec 10, 2019

I added TextArea component to the CSB, but I am having a hard time figuring out how to preserver the value of uploaded file - see FileInput component. Any ideas @JeromeDeLeon @bluebill1049 ?

@njuro
Copy link
Author

njuro commented Dec 10, 2019

I investigated: I can cache the event in onChangeEvent method just fine and then log it:

function handleChange([event]) {
    const file = event.target.files[0];
    console.log(file);
}

But as soon as I try to return {value: file} or setValue(name, file) I get InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

I made temporary workaround by passing a callback to FileInput which will store the uploaded file in parent component's state but that is not optimal. Can you think of something? Thanks.

@bluebill1049 bluebill1049 reopened this Dec 10, 2019
@bluebill1049
Copy link
Member

do you have a codesandbox for this?

@njuro
Copy link
Author

njuro commented Dec 11, 2019

@bluebill1049 yes I added it here https://codesandbox.io/s/dazzling-napier-ne3e6 see form/FileInput.js

@bluebill1049
Copy link
Member

hey @njuro, after some investigation: you will need to use onChangeEvent for input file.

@njuro
Copy link
Author

njuro commented Dec 14, 2019

@bluebill1049 thanks, can you provide an example please? I am already using onChangeEvent in my codesandbox, but it generates said error

@njuro njuro closed this as completed Dec 14, 2019
@njuro njuro reopened this Dec 14, 2019
@bluebill1049
Copy link
Member

oh that's right @njuro i will do it today :)

@bluebill1049
Copy link
Member

use this :)

function handleChange([event]) {
    return {
      value: event.target.value
    };
  }

@njuro
Copy link
Author

njuro commented Dec 14, 2019

@bluebill1049 event.target.value contains only path/filename e.g. C:/fakepath/image.jpg, not the file content itself

@bluebill1049
Copy link
Member

what about e.target.files?

@bluebill1049 bluebill1049 reopened this Dec 14, 2019
@bluebill1049
Copy link
Member

do you have reference on how semantic UI does it for onChange with input file?

@njuro
Copy link
Author

njuro commented Dec 14, 2019

I have no problem accessing the File object through event.target.files as I demonstrated in that CSB, I can log it to console. The issue happens when I try to assign the File object to value property either through setValue or through return { value: file }

@bluebill1049
Copy link
Member

how does semantic UI handle onChange?

@bluebill1049
Copy link
Member

worse case you may have to

function handleChange([event]) {
   setValue() // you probably already doing that
    return {
      value: event.target.value
    };
  }

@njuro
Copy link
Author

njuro commented Dec 15, 2019

@bluebill1049 Yeah, that's probably the best approach now. Closing this, thanks for you effort :)

@njuro njuro closed this as completed Dec 15, 2019
@bluebill1049
Copy link
Member

my pleasure :) @njuro 🙏

@alexfertel
Copy link

@bluebill1049 I have the same issue. Is there any way to solve this? I cannot use setValue in the onChange event of a raw input. I also tried onChageEvent with no luck.

@bluebill1049
Copy link
Member

bluebill1049 commented Oct 31, 2020

@bluebill1049 I have the same issue. Is there any way to solve this? I cannot use setValue in the onChange event of a raw input. I also tried onChageEvent with no luck.

Could you please share a codesandbox? also why you probably should consider to use Controller as this component is no longer maintained.

@alexfertel
Copy link

@bluebill1049 Sorry, I had the following misconception: inputs with a type of file can be controlled, which was cleared by the reactjs docs.

In React, an <input type="file" /> is always an uncontrolled component because its value can only be set by a user, and not programmatically.

I was trying to solve a problem the wrong way. I just used a hidden input (<input type="hidden" {...} />) and that was it 😁

Thank you for this great library and for the quick response! Have a good weekend!

@bluebill1049
Copy link
Member

@bluebill1049 Sorry, I had the following misconception: inputs with a type of file can be controlled, which was cleared by the reactjs docs.

In React, an <input type="file" /> is always an uncontrolled component because its value can only be set by a user, and not programmatically.

I was trying to solve a problem the wrong way. I just used a hidden input (<input type="hidden" {...} />) and that was it 😁

Thank you for this great library and for the quick response! Have a good weekend!

no worries at all 👍 glad it's working out. you have a great weekend too.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants