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

commented Jul 12, 2017

very useful. Thank you.

@danielezn

This comment has been minimized.

Copy link

commented Jul 27, 2017

๐Ÿ‘

@erickakoyama

This comment has been minimized.

Copy link

commented Oct 13, 2017

๐Ÿ‘

@bad6e

This comment has been minimized.

Copy link

commented Nov 7, 2017

Much thanks!

@clementtalleu

This comment has been minimized.

Copy link

commented Dec 23, 2017

muchas gracias <3

@barsbek

This comment has been minimized.

Copy link

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

commented Jan 17, 2018

Works well! thanks

@Shrikant9

This comment has been minimized.

Copy link

commented Jan 18, 2018

๐Ÿ‘

@alexpacer

This comment has been minimized.

Copy link

commented Feb 8, 2018

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

@juliofarah

This comment has been minimized.

Copy link

commented Feb 18, 2018

๐Ÿ‘

@Alexgalinier

This comment has been minimized.

Copy link

commented Mar 9, 2018

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

@VincentNewkirk

This comment has been minimized.

Copy link

commented Mar 13, 2018

๐Ÿ‘

@noushad-pp

This comment has been minimized.

Copy link

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

commented Mar 23, 2018

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

@wootencl

This comment has been minimized.

Copy link

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

commented Jul 3, 2018

Thanks! Really helpful!

@keshamtravels

This comment has been minimized.

Copy link

commented Aug 4, 2018

well done

@obbaeiei

This comment has been minimized.

Copy link

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

commented Aug 15, 2018

๐Ÿ‘

@0t3dWCE

This comment has been minimized.

Copy link

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

commented Aug 16, 2018

@0t3dWCE
I see. Thank you.

@prince1456

This comment has been minimized.

Copy link

commented Aug 22, 2018

Thank you its work fine for me too

@jose920405

This comment has been minimized.

Copy link

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

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

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

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.

@LucasWG94

This comment has been minimized.

Copy link

commented Sep 6, 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

Thanks

@OlMrGreen

This comment has been minimized.

Copy link

commented Sep 16, 2019

๐Ÿ‘

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.