Reputation: 809
What I'm trying to achieve: Get data from a nested element.
How I tried to achieve it: Use ref
attribute of a child to get that element in the parent. Doesn't work because this.refs
appears to only contain refs
in the top component, not nested components.
SubmitStoryForm.jsx
has nested component TextInput.jsx
, which is a simple <input />
component.
So I have two elements in my form, SubmitStoryForm.jsx
:
<TextInput label="Story name" refer="titleInput" />
<textarea className="materialize-textarea" ref="bodyInput" />
The refer
attribute is what is put into the ref
attribute in TextInput
:
import React, {Component, PropTypes,} from 'react';
export default class TextInput extends Component {
render() {
const refer = this.props.refer;
console.log(refer);
const id = 'id_'+refer;
const type = this.props.type;
const col = this.props.col;
const label = this.props.label;
return (
<div className=
{col ? 'input-field col ' + col : 'input-field col s3'}>
<input
placeholder={this.props.placeholder}
id={id}
ref={refer}
type={type ? type : 'text'} />
{label ?
<label for={id}>
{this.props.label}
</label> : ''}
</div>
)
}
}
TextInput.propTypes = {
refer: PropTypes.string.isRequired,
};
Works fine for the textarea
element because the ref
attribute is defined in the parent. But when I pass that responsibility to a child, TextInput
, ref
is not available.
Is this how I should structure my code?
The code fails when I try to do:
this.refs.titleInput.value
in SubmitStoryForm.jsx
, but
this.refs.bodyInput.value
works fine.
Error:
Uncaught TypeError: Cannot read property 'value' of null
Upvotes: 0
Views: 321
Reputation: 14101
While you can use refs
to give a parent access to data of a child component, you really shouldn't. (Netflix, a heavy user of react, even has a rule "no refs, ever" See this video, from about 10m in).
In 99.9% of all cases, anything that you can use refs
for, can be solved better in some other way.
In your example, the parent should not need access to the child's data through refs:
In your case, a better and ref
-less solution would be:
textInputValue
and textAreaValue
onChange()
handler for textarea in your parent (since this component is directly rendered by the parent), which updates statethis.state.textInputValue
and a changeHandler={this.textInputChangeHandler}
as props to your <TextInput>
component<TextInput>
component, add an onChange={this.props.changeHandler}
to the input component, which calls the method on the parent to update stateevent.target.value
to get the new value of the fields.By doing this, you put the input values into state in the parent, and pass one of them as props to the child.
Bonus: in any code to submit your form, you do not need to read all fields again. You can simply get all info from this.state
to send to wherever.
Upvotes: 1