Elcid_91
Elcid_91

Reputation: 1681

Reactjs Retrieving values from custom components

New guy to ReactJS and I am attempting to write a custom component; however, I am stuck on how to retrieve the value of the component in the parent.

Let say I have a custom component input component:

import React,{Component} from "react";

    class TextField extends Component{
      render(){
        const inpStyle = {width:  this.props.width || "100%",height: this.props.height || ""}
        const inpClass = (this.props.error !=="" ? "error" : "")
        const autofocus= this.props.autofocus || false;
        const disabled = typeof this.props.active==="undefined"|| this.props.active===false;
        return(
          <div>
            <label htmlFor={this.props.id}>{this.props.label} </label>
            <input
              className={inpClass}
              style={inpStyle}
              id={this.props.id}
              name={this.props.id}
              value={this.props.value}
              type={this.props.type || "text"}
              disabled={!disabled}
              autoFocus={autofocus}
              placeholder={this.props.placehoder}
              onChange={this.props.handleChange}
              onFocus={this.props.handleFocus}
              onBlur={this.props.handleBlur}
            />
            <div className="errortxt">{this.props.error}</div>
          </div>
        )
      }
    }
    export default TextField

Is there a way to retrieve the component value (the ReactJS way) without the use of refs or do I resort to document.getElementById(...).value

Assuming that state contains the values below and the methods defined are indeed defined in the Parent component:

  render = () => {
    return(
      <div>
        <Panel width="400px" showtitle={false} shadow={true} title="Please Log In" hideclose={true}>
          <TextField
            id="emailaddress"
            label="Email Address:"
            value={this.state.fields.emailaddress.value}
            error={this.state.fields.emailaddress.error}
            autoFocus={this.state.fields.emailaddress.value !== "" ? false : true}
            handleChange={this.handleChange}
            handleFocus={this.handleFocus}
          />

Upvotes: 2

Views: 2285

Answers (3)

andrixb
andrixb

Reputation: 121

It looks that you can either use the dataflow parent/children through props or Refs https://reactjs.org/docs/refs-and-the-dom.html

On top of that, I assume that if you use plain JS method querySelector() you're not taking advantage of React rendering strategies anymore.

Upvotes: 0

Dupocas
Dupocas

Reputation: 21357

React is all about data flowing down in the component's tree. So the state should be owned by Parent. CustomInput receives a value and how to change it from it's parent. Something like this

const Parent = () =>{
    const[value, setValue] = useState('')

    return <CustomInput value={value} setValue={setValue} />
}

const CustomInput = ({ value, setValue }) =>(
    <input className='fancy-input' value={value} onChange={e => setValue(e.target.value) />}
)

This way you can "access" the input's value from Parent without breaking normal flow, and I put access between quotes because you're not actually accessing value, it's a property already onwned by Parent

Upvotes: 6

pmiranda
pmiranda

Reputation: 8470

Create another function, for example:

handleInputChange(event) {
  const target = event.target;
  // Do something with the value
  const value = target.type === 'checkbox' ? target.checked : target.value;
  // Wanna change the value on the input? set a new state, whatever
  const name = target.name;

  this.setState({
    [name]: value
  });
}

In your component:

<input
  onChange={this.handleInputChange}
etc

Upvotes: 0

Related Questions