Search code examples
reactjs

React - passing refs as a prop


I am trying to manage a checkbox with react. The following code works well enough, but I want to refactor out the code in the render method so that it uses a Component. I want to pass the ref to that component, but I cant figure out how to do it.

export default class AreRefsAwesomeCheckbox extends Component {
    constructor(props) {
        super(props);
        this.handleInputChange = this.handleInputChange.bind(this);
    }

    handleInputChange() {
        let data = {
            isFeatured: this.refs.check_me.checked
        };
        postJSON('/some/url', data);
    }


    componentDidMount() {
        const data = getJSON('/some/url');
        data.then(object => {
                this.refs.check_me.checked = object.will_i_have_a_nice_checkbox;
            }
        )
    }

    render() {
        return (
            <div>
                <label>
                    <input ref="check_me" type="checkbox" 
                           onChange={this.handleInputChange}/>
                    <div>Are refs good?</div>
                </label>

            </div>
        );
    }
}

I was thinking about some thing like this

const Checkbox = ({myRef, changeInput, checkboxText}) => {
    return (
        <label>
            <input type="checkbox" ref={myRef} onChange={(event) => changeInput(event)}/>
            <div> {checkboxText} </div>
        </label>)
};

And then putting this snippet in the render method

<Checkbox myRef="check_me" changeInput={this.handleInputChange} checkboxText="Are refs good?"/>

This obviously doesnt work. How do I do this?


Solution

  • Pass a callback ref into the Component, like that:

    <Checkbox myRef={ref => (this.checkbox = ref)} />
    

    Oh, and by the way, please always use callback refs. Read more here.

    One more idea to consider for you: Move the checked value of the checkbox fully into the state of the AreRefsAwesomeCheckbox component and use a fully controlled component. That's always better than a ref with bigger predictability and less surprises.

    Full code:

    const Checkbox = ({myRef, changeInput, checkboxText}) => {
      return (
        <label>
          <input
            type="checkbox"
            ref={myRef}
            onChange={event => changeInput(event)}
          />
          <div> {checkboxText} </div>
        </label>
      )
    }
    
    export default class AreRefsAwesomeCheckbox extends Component {
      constructor(props) {
        super(props)
        this.handleInputChange = this.handleInputChange.bind(this)
      }
    
      handleInputChange() {
        let data = {
          isFeatured: this.refs.check_me.checked,
        }
    
        postJSON('/some/url', data)
      }
    
      componentDidMount() {
        const data = getJSON('/some/url')
        data.then(object => {
          // this.checkbox is the reference to the checkbox element you need
          this.checkbox.checked = object.will_i_have_a_nice_checkbox
        })
      }
    
      render() {
        return (
          <div>
            <label>
              <Checkbox myRef={ref => (this.checkbox = ref)} />
    
              <div>Are refs good?</div>
            </label>
          </div>
        )
      }
    }