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?
There is one caveat to the above example: refs will not get passed through. That's because ref is not a prop. Like key , it's handled differently by React. If you add a ref to a HOC, the ref will refer to the outermost container component, not the wrapped component.
React will pass the ref through and forward it down to <input ref={ref}> by specifying it as a JSX attribute. When the ref is attached, ref. current will point to the <input> DOM node. The second ref argument in the InputRef component only exists when you define a component with React.
To create a ref in a functional component we use the useRef() hook which returns a mutable object with a . current property set to the initialValue we passed to the hook. This returned object will persist for the full lifetime of the component. Thus, throughout all of its re-rendering and until it unmounts.
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>
)
}
}
Use createRef to create the ref that you end up passing down.
If you're passing a ref to a function component use React.forwardRef.
If you're passing a ref down to a class component ensure that the prop name is anything except ref
or you'll get a special prop warning.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With