Data binding in React

Reactjs

Reactjs Problem Overview


What I want to do is when I type some text in an input field, it should appear in another place realtime.

Below is my input;

<div className="post_input">
    <input className='post_data_input_overlay' placeholder="Ask your question here" ref="postTxt"/>
</div>

How can I achieve that?

Reactjs Solutions


Solution 1 - Reactjs

Data binding in React can be achieved by using a controlled input. A controlled input is achieved by binding the value to a state variable and a onChange event to change the state as the input value changes.

See the below snippet

class App extends React.Component {
  constructor() {
    super();
    this.state = { value: 'Hello World' };
  }
  handleChange = (e) => {
    this.setState({ value: e.target.value });
  };
  render() {
    return (
      <div>
        <input
          type="text"
          value={this.state.value}
          onChange={this.handleChange}
        />
        <p>{this.state.value}</p>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="app"></div>


Update: React Hooks

Here is an equivalent function component of the class defined above.

const { useState } = React;

const App = () => {
  const [value, setValue] = useState('Hello World');
  const handleChange = (e) => setValue(e.target.value);
  return (
    <div>
      <input type="text" value={value} onChange={handleChange} />
      <p>{value}</p>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById('app'));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Solution 2 - Reactjs

To be short, in React, there's no two-way data-binding.

So when you want to implement that feature, try define a state, and write like this, listening events, update the state, and React renders for you:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  render() {
    return (
      <input type="text" value={this.state.value} onChange={this.handleChange} />
    );
  }
}

Details here https://facebook.github.io/react/docs/forms.html

UPDATE 2020

> Note: > > LinkedStateMixin is deprecated as of React v15. The recommendation is > to explicitly set the value and change handler, instead of using > LinkedStateMixin.

above update from React official site . Use below code if you are running under v15 of React else don't.

There are actually people wanting to write with two-way binding, but React does not work in that way. If you do want to write like that, you have to use an addon for React, like this:

var WithLink = React.createClass({
  mixins: [LinkedStateMixin],
  getInitialState: function() {
    return {message: 'Hello!'};
  },
  render: function() {
    return <input type="text" valueLink={this.linkState('message')} />;
  }
});

Details here https://facebook.github.io/react/docs/two-way-binding-helpers.html

For refs, it's just a solution that allow developers to reach the DOM in methods of a component, see here https://facebook.github.io/react/docs/refs-and-the-dom.html

Solution 3 - Reactjs

With introduction of React hooks the state management (including forms state) became very simple and, in my opinion, way more understandable and predictable comparing with magic of other frameworks. For example:

const MyComponent = () => {
    const [value, setValue] = React.useState('some initial value');
    return <input value={value} onChange={e => setValue(e.target.value)} />;
}

This one-way flow makes it trivial to understand how the data is updated and when rendering happens. Simple but powerful to do any complex stuff in predictable and clear way. In this case, do "two-way" form state binding.

The example uses the primitive string value. Complex state management, eg. objects, arrays, nested data, can be managed this way too, but it is easier with help of libraries, like Hookstate (Disclaimer: I am the author of this library). Here is the example of complex state management.

When a form grows, there is an issue with rendering performance: form state is changed (so rerendering is needed) on every keystroke on any form field. This issue is also addressed by Hookstate. Here is the example of the form with 5000 fields: the state is updated on every keystore and there is no performance lag at all.

Solution 4 - Reactjs

To bind a control to your state you need to call a function on the component that updates the state from the control's event handler.

Rather than have an update function for all your form fields, you could create a generic update function using ES6 computed name feature and pass it the values it needs inline from the control like this:

class LovelyForm extends React.Component {
  constructor(props) {
  alert("Construct");
    super(props);
    this.state = {
      field1: "Default 1",
      field2: "Default 2"
    };
  }

  update = (name, e) => {
    this.setState({ [name]: e.target.value });
  }

  render() {
    return (
      <form>
        <p><input type="text" value={this.state.field1} onChange={(e) => this.update("field1", e)} />
          {this.state.field1}</p>
        <p><input type="text" value={this.state.field2} onChange={(e) => this.update("field2", e)} />
          {this.state.field2}</p>
      </form>
    );
  }
}
ReactDOM.render(<LovelyForm/>, document.getElementById('example'));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="example"></div>

Solution 5 - Reactjs

> This could be achieved with a hook. However, I would not recommend it, as it strictly couples state and layout.

November 2019 Data Bind with Hooks

const useInput = (placeholder, initial) => {
	const [value, setVal] = useState(initial)
	const onChange = (e) => setVal(e.target.value)
	const element = <input value={value} onChange={onChange} placeholder={placeholder}/>
	return {element, value}
}

Use it in any functional component

const BensPlayGround = () => {
	const name = useInput("Enter name here")
	return (
		<>
			{name.element}
			<h1>Hello {name.value}</h1>
		</>
	)
}

Basic version - bind value and onChange

const useDataBind = () => {
	const [value, setVal] = useState("")
	const onChange = (e) => setVal(e.target.value)
	return {value, onChange}
}

const Demo = (props) => {
	const nameProps = useDataBind()
    return (
        <>
            <input {...nameProps} placeholder="Enter name here" />
            <h1>Hello {nameProps.value}</h1>
        </>
    )
}

Solution 6 - Reactjs

January 2022

Using hooks you can write a custom component which does exactly what you want.

I used TypeScript in the example below:

// InputBind.tsx

import {useState} from 'react';

export interface Binder {
    value: string;
    setter: (value: string) => void;
}

/**
 * Hook that returns a value to be used with InputBind component.
 */
export function useBind(initialValue: string): Binder {
    const [value, setter] = useState(initialValue);
    return {value, setter};
}

/**
 * Custom input component with binding.
 */
export function InputBind({value}: {value: Binder}) {
    return <input type="text" value={value.value}
        onChange={e => value.setter(e.target.value)} />;
}

This is how you use it:

import {InputBind, useBind} from './InputBind';

function Foo() {
    const name = useBind('john');

    console.log('Value is', name.value);

    return (
        <div>
            <div>The name is {name.value}.</div>
            <InputBind value={name} />
        </div>
    );
}

The example above is very simple. The concept can be expanded to other input types and selects as well.

Solution 7 - Reactjs

With the new feature called Hooks from the React team which makes functional components to handle state changes.. your question can be solved easily

import React, { useState, useEffect } from 'react'
import ReactDOM from 'react-dom';

const Demo = props =>{
    const [text, setText] = useState("there");
    return props.logic(text, setText);
};

const App = () => {
    const [text, setText] = useState("hello");

    const componentDidMount = () =>{
        setText("hey");
    };
    useEffect(componentDidMount, []);

    const logic = (word, setWord) => (
        <div>
            <h1>{word}</h1>
            <input type="text" value={word} onChange={e => setWord(e.target.value)}></input>
            <h1>{text}</h1>
            <input type="text" value={text} onChange={e => setText(e.target.value)}></input>
        </div>
    );
    return <Demo logic={logic} />;
};

ReactDOM.render(<App />,document.getElementById("root"));

Solution 8 - Reactjs

class App extends React.Component {
  constructor() {
    super();
    this.state = {value : ''}
  }
  handleChange = (e) =>{ 
    this.setState({value: e.target.value});
  }
  render() {
    return (
    <div>
        <input type="text" value={this.state.value} onChange={this.handleChange}/>
        <div>{this.state.value}</div>
    </div>
   )
  }
}
ReactDOM.render(<App/>, document.getElementById('app'));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="app"></div>

Solution 9 - Reactjs

> There are actually people wanting to write with two-way binding, but React does not work in that way.

That's true, there are people who want to write with two-way data binding. And there's nothing fundamentally wrong with React preventing them from doing so. I wouldn't recommend them to use deprecated React mixin for that, though. Because it looks so much better with some third-party packages.

import { LinkedComponent } from 'valuelink'

class Test extends LinkedComponent {
    state = { a : "Hi there! I'm databinding demo!" };
    
    render(){
        // Bind all state members...
        const { a } = this.linkAll();

        // Then, go ahead. As easy as that.
        return (
             <input type="text" ...a.props />
        )
    }
}

The thing is that the two-way data binding is the design pattern in React. Here's my article with a 5-minute explanation on how it works

Solution 10 - Reactjs

Define state attributes. Add universal handleChange event handler. Add name param to input tag for mapping.

this.state = { stateAttrName:"" }

handleChange=(event)=>{
    this.setState({[event.target.name]:event.target.value });
  } 

<input className="form-control" name="stateAttrName" value= 
{this.state.stateAttrName} onChange={this.handleChange}/>

Solution 11 - Reactjs

Some modules makes simpler data-binding in forms, for example:

react-distributed-forms

class SomeComponent extends React.Component {
  state = {
    first_name: "George"
  };
 
  render() {
    return (
      <Form binding={this}>
        <Input name="first_name" />
      </Form>
    );
  }
}

https://www.npmjs.com/package/react-distributed-forms#data-binding

It uses React context, so you don't have to wire together input in forms

Here's a live demo

Solution 12 - Reactjs

Don't need to Break head with setState() in react.js

A new library made by me React-chopper

Code Like angularjs in reactjs

Code without setState in reactjs

Go through examples for more description

import React, { Component } from 'react';
import { render } from 'react-dom';
import Rcp from 'react-chopper';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'React'
    };
    this.modal = Rcp(this.state, this);
  }

  tank = () => {
    console.log(this.modal)
  }
  render() {
    return (
      <div>
        <input value={this.modal.name} onChange={e => this.modal.name = e.target.value} />
        <p> Bang Bang {this.modal.name} </p>
        <button onClick={() => this.tank()}>console</button>
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

Comments , Pr Are welcome ...Enjoy

Solution 13 - Reactjs

I think @Richard Garside is correct.

I suggest some changes to clear even more the code.

Change this

onChange={(e) => this.update("field2", e)}

To this

onChange={this.handleOnChange}

And also, change this

this.setState({ [name]: e.target.value });

To this

this.setState({ [e.target.name]: e.target.value})

Besides, you have to add the "name" attribute to the field with a value that relates with the key on the state object.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCraZyDroiDView Question on Stackoverflow
Solution 1 - ReactjsShubham KhatriView Answer on Stackoverflow
Solution 2 - ReactjsjiyinyiyongView Answer on Stackoverflow
Solution 3 - ReactjsAndrewView Answer on Stackoverflow
Solution 4 - ReactjsRichard GarsideView Answer on Stackoverflow
Solution 5 - ReactjsBen CarpView Answer on Stackoverflow
Solution 6 - ReactjsrodrigocfdView Answer on Stackoverflow
Solution 7 - ReactjsDhiraj KumarView Answer on Stackoverflow
Solution 8 - ReactjsGitesh KumarView Answer on Stackoverflow
Solution 9 - ReactjsgapertonView Answer on Stackoverflow
Solution 10 - ReactjsdvirovecView Answer on Stackoverflow
Solution 11 - ReactjsSLVView Answer on Stackoverflow
Solution 12 - ReactjsvijayView Answer on Stackoverflow
Solution 13 - ReactjsManeviMatiasView Answer on Stackoverflow