Krzysztof Żuraw blog

Debouncing forms in React with Redux - part one

February 10, 2018

Hi! Today I want to start a new blog post series. This one will be all about debouncing react forms. Let’s get started!

Basic react form

Before we jump into debouncing and what it means I want to present you a simple react form. It looks like this:

image

I made this using awesome Tailwind CSS. The code for this form sits mainly in two components - App.js:

class App extends Component {
  constructor(props) {
    super(props)
    this.state = { typedWords: [] }
  }

  handleChange = event => {
    const { value } = event.target
    let typedWords = [...this.state.typedWords, value]
    this.setState({ typedWords })
  }
  render() {
    return (
      <div className="flex flex-col items-center min-h-screen w-full bg-teal-lighter bg-repeat">
        <div className="container md:max-w-sm md:mx-auto">
          <h1 className="block w-full text-center text-grey-darkest mb-6">
            Debounce in React
          </h1>
          <SearchInput handleChange={this.handleChange} />
        </div>
        {this.state.typedWords.map((word, key) => (
          <SearchResult text={word} key={key} />
        ))}
      </div>
    )
  }
}

and SearchInput:

class SearchInput extends Component {
  render() {
    const { handleChange } = this.props
    return (
      <form className="mb-4" onChange={handleChange}>
        <div className="flex flex-col mb-4 md:w-full">
          <label
            className="mb-2 uppercase font-bold text-lg text-grey-darkest"
            htmlFor="search-input"
          >
            Search input:
          </label>
          <input className="field" name="search" type="text" id="search" />
        </div>
      </form>
    )
  }
}

How it works

In my App component I define a handleChange function which then will be used inside SearchInput as a callback. In handleChange, I extract typed character from html input. Then I make a copy of state and insert a new value from SearchInput component.

SearchInput is representing html form so I treat it as a representational component.

You may notice another component - SearchResult which looks like this:

function SearchResult(props) {
  const { text } = props
  return (
    <div className="container md:max-w-sm md:mx-auto">
      <span>{text}</span>
    </div>
  )
}

it is still only representing html.

I have my components working so let’s type something into a search input:

Form without debouncing from Noaal on Vimeo.

Whoa! What is happening here?

onChange event handler fired up every time I typed something into an input. That’s not exactly what I wanted - I want my handler to capture only full typed words. How to do it?

By using debouncing - which I will explain in next blog post! Stay tuned and thanks for reading.


Krzysztof Żuraw

Written by Krzysztof Żuraw who lives and works in Wrocław. About page.