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

Material UI - label overlap when using setValue #2192

Closed
michalbundyra opened this issue Jul 13, 2020 · 16 comments
Closed

Material UI - label overlap when using setValue #2192

michalbundyra opened this issue Jul 13, 2020 · 16 comments

Comments

@michalbundyra
Copy link
Contributor

Describe the bug
I am using material-ui with react-hook-form. I am loading some data in useEffect hook and I'd like to set these to the form.
Unfortunately when I do that, the label is overlapping the value (value is set to the field).

I guess I can use value + onChange but I am not sure if it is the best solution (performance?).

To Reproduce
Please see codesandbox link below

Codesandbox link (Required)

https://codesandbox.io/s/react-hook-form-useform-template-5egkh?fontsize=14&hidenavigation=1&theme=dark

Expected behavior

Label is not overlapped with the field value.

Screenshots
image

Desktop (please complete the following information):

  • OS: macOS
  • Browser Chrome/Safari
  • Version 83.0.4103.116/13.1.1
@michael-land
Copy link
Contributor

It has nothing to do with this lib.

@michalbundyra
Copy link
Contributor Author

@xiaoyu-tamu

It has nothing to do with this lib.

How come?
If I add value="John" attr label and value is rendered properly. The problem is when I am using setValue and this is part of react-hook-form interface.

@michael-land
Copy link
Contributor

Have you check this limitation? https://material-ui.com/components/text-fields/#limitations

Your CSB looks good on my laptop.

image

@bluebill1049
Copy link
Member

hey @michalbundyra please use Controller for this, because MUI only will move the label when external prop (value) gets updated, it doesn't check whether the input value has been updated. so Controller will solve that problem for you, you can easily use <Controller as={TextField} control={control} name='test' />

@michalbundyra
Copy link
Contributor Author

@bluebill1049 Thanks for your answer. I am afraid that it does not work, see:

https://codesandbox.io/s/react-hook-form-useform-template-kqhqv

image

... but I see the problem now only on Safari, not on Chrome anymore. In my application I can still see the same problem in Chrome, also when I use Controller. So far I do not have a valid solution for that problem...

@bluebill1049
Copy link
Member

Screen Shot 2020-07-14 at 1 40 23 pm

here you go in Safari:

https://codesandbox.io/s/react-hook-form-useform-template-czc4r?file=/src/index.js

@michalbundyra
Copy link
Contributor Author

@bluebill1049 Thanks! SOLVED. I guess defaultValue="" + Controller was a key here. Thanks again :)

@bluebill1049
Copy link
Member

please have a read the doc under Controller @michalbundyra. There are some really useful info there: https://react-hook-form.com/api#Controller

@OnkelTem
Copy link

OnkelTem commented Dec 12, 2020

We experience a similar problem on all of our forms on several projects.
And we don't use any setValue or something, just a regular MUI TextField.

Here is an example:

<TextField label="Name" name={name} inputRef={register} />
<TextField label="Name" defaultValue={'foo-bar-2'} />

and here is the result:

image

As you see, the field's "shrink" state to the left wasn't updated after receiving the value from form data.

Does this mean that we should also wrap basic TextField in Controller?

@OnkelTem
Copy link

OnkelTem commented Dec 12, 2020

Yeah, it worked with the Controller:

<Controller
  as={TextField}
  label="Name"
  control={control}
  name={name}
/>

Actually the docs made this confusion.

Here: https://react-hook-form.com/get-started#IntegratingwithUIlibraries the first example for the TextField reads:

<TextField inputRef={register} name="FirstName"/>

which basically doesn't work.

Maybe it's worth updating the docs then?

@bluebill1049
Copy link
Member

bluebill1049 commented Dec 14, 2020

No, that doesn't actually work.
If I reload the page with such a Control, it doesn't get its label shrinked.

I know it's not related, but I didn't have any issues like this with React Final Form. So if you folks haven't yet decided with what library to proceed maybe it's worth checking out React Final Form instead.

what's not working? where is the codesandbox? I fork the link above: https://codesandbox.io/s/react-hook-form-useform-template-forked-kmmeo?file=/src/index.js which i have posted.

@react-hook-form react-hook-form deleted a comment from OnkelTem Dec 14, 2020
@72ridwan
Copy link

As far as I know, Material-UI has internal state to check whether a field is filled or not. The state is available in FormControl, which it passes down to every children with FormControlContext. TextField is one component that uses FormControl.

This filled state is used by MUI's InputLabel to determine whether the label should shrink or not.

When the field is uncontrolled and the value changed through setting HTMLInputElement.value directly, this changed value is not reflected in the filled state of FormControl. To fix this you'd have to change the filled state by yourself.

Here's a demo that shows how to change the filled state based on RHF's form value while keeping the field uncontrolled:
https://codesandbox.io/s/rhf-mui-refreshing-filled-state-wtti9

The trick is to listen to FormControlContext by becoming its children (through end adornment in InputProps) and set filled state using onFilled and onEmpty that are exposed by FormControlContext with useFormControl.

@LuanPianeli07
Copy link

InputLabelProps={{ shrink: true }}

@deeksha-prabhakar
Copy link

For me it was the order, label had to come before value
<TextField name={name} variant="outlined" label={label} InputLabelProps={{ shrink: true }} value={value} onChange={handleChange} onBlur={handleBlur} />

@appinsource2021
Copy link

appinsource2021 commented Apr 19, 2022

With Class component

`class MyComponent extends Component {

constructor(props){
    super(props);

    this.state = {
        data:{},
        shrink:true
    };

}

componentDidMount() {

    fetch('/to/api/url' )
        .then( res => res.json() )
        .then( res => {
            this.setState({data: res}) ;
        })
        .catch(e => {
            console.error(e);
        })
}

render() {

    return (
        <div>

            <TextField
                id="outlined-helperText"
                label="Field name"
                value={this.state.data.name}
                InputLabelProps={{ shrink: this.state.shrink }}
                onFocus={ e => { this.setState({shrink: true}) }}
                onBlur={ e => { this.setState({shrink: e.target.value.length ? true:false}) }}
                onChange={ e => {this.setState({client: e.target.value })}}
                helperText="Some important text"
            />
            

        </div>
    );
}

}`

@fredrivett
Copy link

In my instance the issue was the form element going from uncontrolled to controlled.

As others have said, the way to fix it was to set a defaultValue of "" if no specific defaultValue was set, rather than letting it be undefined.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 8, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants