2

If I create a component like this:

const MyInput = ({username})=>{
        return (
         <div>
            <input type="text" value={username}/>
         </div>
        );
};

nothing will happen when I type in the input, because react needs to call setState() to update it.

so what I do is add a onChange method to handle it:

handleOnchange(e){
    e.preventDefault();
        let name=e.target.value;
  this.setState({username:name});
}

But I think having to handle every onChange manually is too much boilerplate, Is this a better way to save the value? can it be done using ref?

Fiddle Link

Yichz
  • 9,250
  • 10
  • 54
  • 92
  • 1
    my short answer: use `ref` if you are submiting a from, use `state` if you are updating some data somewhere in the component. – elreeda Jul 08 '16 at 00:45
  • if I use ref for submitting a form, is there anyway to bind the values to props? otherwise, all form elements would be in the same container, isn't it? – Yichz Jul 08 '16 at 00:57
  • 1
    you will understand everything [here](http://stackoverflow.com/questions/29503213/use-state-or-refs-in-react-js-form-components) – elreeda Jul 08 '16 at 00:59
  • @Kossel by "too much boiler plate" what exactly do you mean? Are you referring to the fact that this will generate a lot of setStates? – Dr. Nitpick Jul 08 '16 at 02:24
  • @Dr. Nitpick I mean, a lot of setState, bind(this), and handleOnChange() – Yichz Jul 08 '16 at 04:46
  • Cool, I think I got an answer for ya then – Dr. Nitpick Jul 08 '16 at 04:59

4 Answers4

2

Yes, you need to call setState in order for the value to update on the input.

See here for a good example: https://facebook.github.io/react/docs/forms.html

Copied here:

getInitialState: function() {
    return {value: 'Hello!'};
  },
  handleChange: function(event) {
    this.setState({value: event.target.value});
  },
  render: function() {
    return (
      <input
        type="text"
        value={this.state.value}
        onChange={this.handleChange}
      />
    );
  }
Scott
  • 3,736
  • 2
  • 26
  • 44
0

There is a solution to this issue that is common in javascript and implemented by lodash. Take a look at using debouncing to wait for the user to stop entering text before trying to update. Here is an analogy of how it works from someone more eloquent than me:

Think of it as "grouping multiple events in one". Imagine that you go home, enter in the elevator, doors are closing... and suddenly your neighbor appears in the hall and tries to jump on the elevator. Be polite! and open the doors for him: you are debouncing the elevator departure. Consider that the same situation can happen again with a third person, and so on... probably delaying the departure several minutes.

To do this in react you would import lodash and set onChange to be _.debounce(function(), delay) where function() would setState after the given delay.

This demo does a great job demoing how debounce works in react (just open the console and watch it as you type).

If you want to learn about best practices with debounced functions read the answers in this SO post.

Ps: you can also try throttling, though I think debouncing will be more desirable for your specific use case. The post with the analogy on debouncing also has one on throttling. To use it you would replace _.debounce(function, int) with _.throttle(function, int) in the examples

Community
  • 1
  • 1
Dr. Nitpick
  • 1,662
  • 1
  • 12
  • 16
  • I don't think OP has issues handeling every single instance of the event (yet) but wonders if it won't be too unwieldy to type this in for every input on the form. – flup Jul 08 '16 at 05:39
  • Awww shucks. I was split on what exactly he meant. Thanks for the clarification! – Dr. Nitpick Jul 08 '16 at 13:00
0

You can value link in react to implement 2 way data binding

class Something extends React.Component {
    state = {
        email: ''
    }

    emailValueLink = (value) => {
        return {
            value: this.state.email,
            requestChange: this.handleEmailChange
        };
    }

    handleEmailChange(newEmail) {
        this.setState({email: newEmail});
    }

    render() {
        <input type="email" valueLink={this.emailValueLink()} />
    }
}

You can generalise emailValuelink by passing it in the key of the state to bind

Piyush.kapoor
  • 6,715
  • 1
  • 21
  • 21
-1

React is all about splitting your code into components. So to prevent retyping this boilerplate code, you can create a component and reuse it for all form elements. Or, like others have said, you can take somebody else's form or databinding components and reuse those.

flup
  • 26,937
  • 7
  • 52
  • 74