alexsouye
alexsouye

Reputation: 740

How to handleChange a TextInput component?

I have make this TextInput component

export const TextInput = (props) => {
  const { label } = props
  return (
    <div className="field text">
      <input type="text" />
      <label>{label}</label>
    </div>
  )
}

But at the call of this component, I would like to handleChange each input according to its name

handleChange = (e) => this.setState({ [e.target.name]: e.target.value })


<TextInput
   label="Email"
   name="email"
   value={this.state.email}
   onChange={this.handleChange}
/>

The problem is that my state and my method are not in the component.

I have to pass my method in props?

Upvotes: 2

Views: 1240

Answers (5)

Joseph D.
Joseph D.

Reputation: 12174

The problem is that my state and my method are not in the component.

It's actually not a problem. You are doing the right thing.

It's what React calls as Lifting State Up.

So just use the props in your child component.

export const TextInput = (props) => {
  const { label } = props
  return (
    <div className="field text">
       // use props
      <input type="text"
        onChange={props.onChange}
        name={props.name}
        value={props.value}
      />
      <label>{label}</label>
    </div>
  )
}

Upvotes: 2

thortsx
thortsx

Reputation: 2280

So, you should create TextInput like this:

export const TextInput = (props) => {
  const { 
     name,
     label,
     value,
     onChange,
     disabled,
     customClass,
      ...others
  } = props
  return (
    <div className="field text">
      <input 
         className={customClass}
         name={name}
         type="text"
         disabled={disabled}
         value={value}
         onChange={e => onChange(e)} // I will return event here, not currenTarget.value
         {...others}
      />
      <label>{label}</label>
    </div>
  )
}

And then, you can use TextInput as an input element like this:

<TextInput
   label="Email"
   customClass="class-custom-input"
   disabled={false}
   name="email"
   value={this.state.email}
   onChange={this.handleChange} // at here you can received an `event`
   onClick={...} // will be pass as ...others in TextInput
   onBlur={...} // will be pass as ...others in TextInput
/>

Upvotes: 2

Jorge Ortega
Jorge Ortega

Reputation: 41

You can use the useRef hook and pass it to the TextInput component.

const emailRef = useRef(null)

handleChange = () => this.setState({ [emailRef.current.name]: emailRef.current.value })


<TextInput
   label="Email"
   name="email"
   value={this.state.email}
   onChange={this.handleChange}
   ref={emailRef}
/>

Upvotes: 1

Harmenx
Harmenx

Reputation: 946

Try adding the onChange to the child component

export const TextInput = (props) => {
  const { label } = props
  return (
    <div className="field text">
      <input onChange={props.onChange} type="text" />
      <label>{label}</label>
    </div>
  )
}

Upvotes: 1

Clarity
Clarity

Reputation: 10873

You need to enable the onChange handler on input first:

export const TextInput = (props) => {
  const { label } = props
  return (
    <div className="field text">
      <input type="text" onChange={props.onChange}/>
      <label>{label}</label>
    </div>
  )
}

Upvotes: 1

Related Questions