avoid constant re-render from "input" or "textarea" in react js

As @Chris stated, you should create another component to optimize the rerendering to only the specified component.

However, there are usecases where you need to update the parent component or dispatch an action with the value entered in your input to one of your reducers.

For example I created a SearchInput component which updates itself for every character entered in the input but only call the onChange function only if there are 3 characters at least.

Note: The clearTimeout is useful in order to call the onChange function only when the user has stopped typing for at least 200ms.

import React from 'react';

class SearchInput extends React.Component {
  constructor(props) {
    super(props);
    this.tabTimeoutId = [];
    this.state = {
      value: this.props.value,
    };

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

  componentWillUpdate() {
    // If the timoutId exists, it means a timeout is being launch
    if (this.tabTimeoutId.length > 1) {
      clearTimeout(this.tabTimeoutId[this.tabTimeoutId.length - 2]);
    }
  }

  onChangeSearch(event) {
    const { value } = event.target;

    this.setState({
      value,
    });

    const timeoutId = setTimeout(() => {
      value.length >= this.props.minSearchLength ? this.props.onChange(value) : this.props.resetSearch();
      this.tabTimeoutId = [];
    }, this.props.searchDelay);

    this.tabTimeoutId.push(timeoutId);
  }

  render() {
    const {
      onChange,
      minSearchLength,
      searchDelay,
      ...otherProps,
    } = this.props;

    return <input
      {...otherProps}
      value={this.state.value}
      onChange={event => this.onChangeSearch(event)}
    />
  }
}

SearchInput.propTypes = {
  minSearchLength: React.PropTypes.number,
  searchDelay: React.PropTypes.number,
};
SearchInput.defaultProps = {
  minSearchLength: 3,
  searchDelay: 200,
};

export default SearchInput;

Hope it helps.


Well, that's how you implement controlled input elements in React.

However, if performance is a major concern of yours, you could either isolate your input element in a separate stateful component, hence only triggering a re-render on itself and not on your entire app.

So something like:

class App extends Component {    
  render() {
    return (
      <div>
        ...
        <MyInput />
        ...
      </div>
    );
  }
}


class MyInput extends Component {
  constructor() {
    super();
    this.state = {value: ""};
  }

  update = (e) => {
    this.setState({value: e.target.value});
  }

  render() {
    return (
      <input onChange={this.update} value={this.state.value} />
    );
  }
}

Alternatively, you could just use an uncontrolled input element. For example:

class App extends Component {    
  render() {
    return (
      <div>
        ...
        <input defaultValue="" />
        ...
      </div>
    );
  }
}

Though, note that controlled inputs are generally recommended.

Tags:

Reactjs