Search code examples
reactjsstatelessreact-dom

Resetting Values in ReactDOM Ref children (Best Practices?)


I've got a stateless component, called FlexibleInput.

import React, { PropTypes } from 'react'

export default function FlexibleInput({
  id,
  label,
  defaultValue,
  type,
  onChange,
}){
  let fieldClass = `${id}-field`
  return (
    <fieldset className={fieldClass}>
      <label htmlFor={id}>{label}</label>
      <input
        key={id}
        id={id}
        type={type}
        defaultValue={defaultValue}
        onChange={onChange}
        />
    </fieldset>
  )
}

FlexibleInput.propTypes = {
  id: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  defaultValue: PropTypes.string.isRequired,
  type: PropTypes.string.isRequired, // accepts "text", "password" atm.
  onChange: PropTypes.func.isRequired,
}

I use this FlexibleInput in a form called AddNote.

<form
  className="note-list__add-note"
  onSubmit={this.addNote}
  ref={`${this.props.type}-addNoteForm`}
  >
  <FlexibleInput
    id="note"
    label="Awaiting changes..."
    type="text"
    defaultValue=""
    onChange={(e) => this.setState({ content: e.target.value })}
    />

After submitting using the this.addNote function... I would like to be able to reset the FlexibleInput input value.

I've managed to do a ugly ass hack version...

this.refs[`${this.props.type}-addNoteForm`]
  .childNodes[0].childNodes[1].value = ''

Which manages to properly reset the value. This is prone to change because perhaps the structure of the FlexibleInput will change? I do not know, hopefully not.

But my main question is, is there a way that I could do a sort of

this.refs[bla bla].find(#input)

or so?

It is not very clear in the React/ReactDOM documentation which api is available for a ref.

Thank you!


Solution

  • You could create a Controlled component whereby the value of the input is set using using component state:

    <form
      className="note-list__add-note"
      onSubmit={this.addNote}
      ref={`${this.props.type}-addNoteForm`}
      >
      <FlexibleInput
        id="note"
        label="Awaiting changes..."
        type="text"
        defaultValue=""
        value={this.state.content}
        onChange={(e) => this.setState({ content: e.target.value })}
      />
    

    Then you just need to reset the content value within the this.addNote method:

    addNote() {
      this.setState({ content: '' });
    }
    

    N.B. Ensure you bind addNote correctly to ensure this.setState is correctly referenced.