0

I have a React component with a <textarea> in it. I want this <textarea> to have all of the following characteristics:

  • editable, e.g. must use defaultValue OR (value WITH onChange)
  • initial content determined by incoming prop
  • content automatically changes when incoming props change

If I use defaultValue, then the <textarea> will not update when the component updates due to modified props from the parent.

If I use the value with onChange model as described in the React docs and in this SO answer, I fall into a trap and can't use incoming props from the parent to modify the state of the <textarea> because:

  • the <textarea>'s value must point to its component's state
  • component state can only be set by incoming props in getInitialState; setState can't be used in componentDidUpdate, for example; so I can never update state, and thus the value of my <textarea>, on a re-render

So my question is, how can I have a <textarea> in ReactJS whose value can be updated by the user, by incoming props on initial load, and also by updates to incoming props?

The only nasty workaround I've thought of so far is to use a "non-managed" state, my own JSON props tacked onto the component in place of formal React state. But this is not "the React way."

Simplified code follows in case it helps.

This code works on initial component load, but never uses props again so can't update the <textarea> content from props.

var Input = React.createClass({
  componentDidUpdate: function() {
    // when component updates, can't use setState here to update state,
    // and thus can't update <textarea> content
  },
  getInitialState: function() {
    return {
      draftPath: this.props.draftPath,
      draftBody: this.props.draftBody
    };
  },
  handlePathChange: function(event) {
    this.setState({
      draftPath: event.target.value
    });
  },
  handleBodyChange: function(event) {
    this.setState({
      draftBody: event.target.value
    });
  },
  render: function() {
    return (
      <div id='cyoag-input-container'>
        <textarea id='cyoag-input-path' type='text'
          value={this.state.draftPath} onChange={this.handlePathChange} >
        </textarea>
        <textarea id='cyoag-input-body' type='text'
          value={this.state.draftPath} onChange={this.handleBodyChange} >
        </textarea>
      </div>
    );
  }
}
Community
  • 1
  • 1
Steverino
  • 2,099
  • 6
  • 26
  • 50

1 Answers1

1

You can use componentWillReceiveProps(nextProps) to update your component state with the incoming property.

Don't forget to compare your component props with the nextProps in order to call setState only if it's necessary.

Freez
  • 7,208
  • 2
  • 19
  • 29