KSHMR
KSHMR

Reputation: 809

meteor - get value from child to parent

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

Answers (1)

wintvelt
wintvelt

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:

  • if the data is about child props, then the parent already knows about the data, and therefore: no refs needed.
  • if the data is about child state, then using refs to access that data is really cheating react: state is not supposed to be directly accessible from outside the component.
  • if the data is not in child props, nor in child state, then it probably is a design omission to be fixed, because data relevant to the app should be either props or state.

In your case, a better and ref-less solution would be:

  • make your parent component stateful, by adding state for textInputValue and textAreaValue
  • add a onChange() handler for textarea in your parent (since this component is directly rendered by the parent), which updates state
  • pass this.state.textInputValue and a changeHandler={this.textInputChangeHandler} as props to your <TextInput> component
  • in your <TextInput> component, add an onChange={this.props.changeHandler} to the input component, which calls the method on the parent to update state
  • in the change handlers in your parent, you can read event.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

Related Questions