Fellow Stranger
Fellow Stranger

Reputation: 34013

Uncontrolled child component with styled-components

I'm trying to create a reusable component that is an uncontrolled input. Normally this works fine, but I cannot get it to work with styled-components applied to the child component (value returns undefined).

class Parent extends Component {
  handleSubmit = (event) => {
    console.log(this.firstName.value)
    event.preventDefault();
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
          <label>First Name</label>
          <UncontrolledInput
            defaultValue={'fish'}
            inputType='text'
            name='firstName'
            inputRef={(element) => {this.firstName = element}}
          />
          <button type="submit">
            Submit
          </button>
      </form>
    )
  }
}


const StyledInput = styled.input`
  border: 3px solid;
`;

const UncontrolledInput = (props) => {
  const {name, inputType, defaultValue, inputRef} = props;
    return (
    <StyledInput
      name={name}
      type={inputType}
      defaultValue={defaultValue ? defaultValue : ''}
      ref={inputRef}
    />
  )
};

Upvotes: 0

Views: 606

Answers (1)

trixn
trixn

Reputation: 16309

styled-components wraps elements into a react component. Passing a ref prop to it will not give you the reference to the DOM element but to the wrapper component.

In the styled-components docs is described how to obtain a ref to the underlying DOM element:

Passing a ref prop to a styled component will give you an instance of the StyledComponent wrapper, but not to the underlying DOM node. This is due to how refs work. It's not possible to call DOM methods, like focus, on our wrappers directly.

To get a ref to the actual, wrapped DOM node, pass the callback to the innerRef prop instead.

So just change ref to innerRef on your <StyledInput>component:

const UncontrolledInput = (props) => {
  const {name, inputType, defaultValue, inputRef} = props;
    return (
    <StyledInput
      name={name}
      type={inputType}
      defaultValue={defaultValue ? defaultValue : ''}
      innerRef={inputRef}
    />
  )
};

Here is a working example.

Upvotes: 1

Related Questions