Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ReactJS: Input fire onChange when user stopped typing (or pressed Enter key)
import React, { Component } from 'react';
import TextField from 'components/base/TextField';
const WAIT_INTERVAL = 1000;
const ENTER_KEY = 13;
export default class TextSearch extends Component {
constructor(props) {
super();
this.state = {
value: props.value
};
}
componentWillMount() {
this.timer = null;
}
handleChange(value) {
clearTimeout(this.timer);
this.setState({ value });
this.timer = setTimeout(::this.triggerChange, WAIT_INTERVAL);
}
handleKeyDown(e) {
if (e.keyCode === ENTER_KEY) {
::this.triggerChange();
}
}
triggerChange() {
const { value } = this.state;
this.props.onChange(value);
}
render() {
const { className } = this.props;
return (
<TextField
className={className}
placeholder={l('Search')}
value={this.state.value}
onChange={::this.handleChange}
onKeyDown={::this.handleKeyDown}
/>
);
}
}
@markkitz

This comment has been minimized.

Copy link

markkitz commented Jul 12, 2017

very useful. Thank you.

@danielezn

This comment has been minimized.

Copy link

danielezn commented Jul 27, 2017

๐Ÿ‘

@erickakoyama

This comment has been minimized.

Copy link

erickakoyama commented Oct 13, 2017

๐Ÿ‘

@bad6e

This comment has been minimized.

Copy link

bad6e commented Nov 7, 2017

Much thanks!

@clementtalleu

This comment has been minimized.

Copy link

clementtalleu commented Dec 23, 2017

muchas gracias <3

@barsbek

This comment has been minimized.

Copy link

barsbek commented Dec 25, 2017

Hi!

  1. Thanks for the gist!
  2. I have encountered double triggerChange method call, when i changed value and immediately pressed enter_key. So, i would suggest to add clearTimeout into handleKeyDown method.
handleKeyDown(e) {
    if (e.keyCode === ENTER_KEY) {
         clearTimeout(this.timer);
        ::this.triggerChange();
    }
}
@lisaljl

This comment has been minimized.

Copy link

lisaljl commented Jan 17, 2018

Works well! thanks

@Shrikant9

This comment has been minimized.

Copy link

Shrikant9 commented Jan 18, 2018

๐Ÿ‘

@alexpacer

This comment has been minimized.

Copy link

alexpacer commented Feb 8, 2018

This is exactly what I'm looking for! Much appreciated ๐Ÿ‘

@juliofarah

This comment has been minimized.

Copy link

juliofarah commented Feb 18, 2018

๐Ÿ‘

@Alexgalinier

This comment has been minimized.

Copy link

Alexgalinier commented Mar 9, 2018

That's really useful and exactly what i was looking for. Thanks !

@VincentNewkirk

This comment has been minimized.

Copy link

VincentNewkirk commented Mar 13, 2018

๐Ÿ‘

@noushad-pp

This comment has been minimized.

Copy link

noushad-pp commented Mar 23, 2018

Sorry for the ignorance.
Can you please explain what :: before your function stands for?

@AOOlivares

This comment has been minimized.

Copy link

AOOlivares commented Mar 23, 2018

@noushad-pp
It's an ECMAScript function bind syntax as proposed here

@wootencl

This comment has been minimized.

Copy link

wootencl commented May 15, 2018

Minor note on using that :: bind syntax: Will take a slight performance hit as the function will need to be bound on every render. At least this is my understanding. To avoid this, binding should occur in the constructor.

@shenoyranjith

This comment has been minimized.

Copy link

shenoyranjith commented Jul 3, 2018

Thanks! Really helpful!

@keshamtravels

This comment has been minimized.

Copy link

keshamtravels commented Aug 4, 2018

well done

@obbaeiei

This comment has been minimized.

Copy link

obbaeiei commented Aug 9, 2018

Thank you

But I have modified some code. It works with my project.

import React, { Component } from 'react'

const WAIT_INTERVAL = 1000
const ENTER_KEY = 13

class TextSearch extends Component {
  state = {
    value: ''
  }

  timer = null

  handleChange = e => {
    clearTimeout(this.timer)

    this.setState({ value: e.target.value })

    this.timer = setTimeout(this.triggerChange, WAIT_INTERVAL)
  }

  handleKeyDown = e => {
    if (e.keyCode === ENTER_KEY) {
      clearTimeout(this.timer)
      this.triggerChange()
    }
  }

  triggerChange = () => {
    const { value } = this.state

    this.props.onChange(value)
  }

  render() {
    const { ...rest } = this.props

    return (
      <input
        type={rest.type}
        className={rest.className}
        placeholder={rest.placeholder}
        value={this.state.value}
        onChange={this.handleChange}
        onKeyDown={this.handleKeyDown}
      />
    )
  }
}

export default TextSearch
@0t3dWCE

This comment has been minimized.

Copy link

0t3dWCE commented Aug 15, 2018

๐Ÿ‘

@0t3dWCE

This comment has been minimized.

Copy link

0t3dWCE commented Aug 16, 2018

@obbaeiei, you should clear timeout inside handleKeyDown too. If your triggerChange will do fetch to backend (via action creator if u use redux), you will see two requests after Enter pressed.

@obbaeiei

This comment has been minimized.

Copy link

obbaeiei commented Aug 16, 2018

@0t3dWCE
I see. Thank you.

@prince1456

This comment has been minimized.

Copy link

prince1456 commented Aug 22, 2018

Thank you its work fine for me too

@jose920405

This comment has been minimized.

Copy link

jose920405 commented Dec 4, 2018

Any way to do this without this.setState({ value });?

Because in reality a change is made in the local state immediately and then a props is dispatched to the parent component.

@ashishcodes4

This comment has been minimized.

Copy link

ashishcodes4 commented Jan 29, 2019

couldn't thank you enough for this, however I was wondering if there is any better way of doing the same.

@ashishcodes4

This comment has been minimized.

Copy link

ashishcodes4 commented Jan 29, 2019

Thank you

But I have modified some code. It works with my project.

import React, { Component } from 'react'

const WAIT_INTERVAL = 1000
const ENTER_KEY = 13

class TextSearch extends Component {
  state = {
    value: ''
  }

  timer = null

  handleChange = e => {
    clearTimeout(this.timer)

    this.setState({ value: e.target.value })

    this.timer = setTimeout(this.triggerChange, WAIT_INTERVAL)
  }

  handleKeyDown = e => {
    if (e.keyCode === ENTER_KEY) {
      clearTimeout(this.timer)
      this.triggerChange()
    }
  }

  triggerChange = () => {
    const { value } = this.state

    this.props.onChange(value)
  }

  render() {
    const { ...rest } = this.props

    return (
      <input
        type={rest.type}
        className={rest.className}
        placeholder={rest.placeholder}
        value={this.state.value}
        onChange={this.handleChange}
        onKeyDown={this.handleKeyDown}
      />
    )
  }
}

export default TextSearch

Hey, can you explain what is type= rest.type attribute in input element.

@ashishcodes4

This comment has been minimized.

Copy link

ashishcodes4 commented Jan 29, 2019

Thank you
But I have modified some code. It works with my project.

import React, { Component } from 'react'

const WAIT_INTERVAL = 1000
const ENTER_KEY = 13

class TextSearch extends Component {
  state = {
    value: ''
  }

  timer = null

  handleChange = e => {
    clearTimeout(this.timer)

    this.setState({ value: e.target.value })

    this.timer = setTimeout(this.triggerChange, WAIT_INTERVAL)
  }

  handleKeyDown = e => {
    if (e.keyCode === ENTER_KEY) {
      clearTimeout(this.timer)
      this.triggerChange()
    }
  }

  triggerChange = () => {
    const { value } = this.state

    this.props.onChange(value)
  }

  render() {
    const { ...rest } = this.props

    return (
      <input
        type={rest.type}
        className={rest.className}
        placeholder={rest.placeholder}
        value={this.state.value}
        onChange={this.handleChange}
        onKeyDown={this.handleKeyDown}
      />
    )
  }
}

export default TextSearch

Hey, can you explain what is type= rest.type attribute in input element.

Never mind, got it, its the rest/spread thing you are using to pass the props passed to the component.
Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You canโ€™t perform that action at this time.