skip to Main Content

DISCLAIMER: i’m new at React, and just trying to build good habits.

So, the example would be a simple contacts app, where you type in names, and all the names are rendered below the input field. pic.1 simple contacts app mechanics

First, and the most intuitive way, of making this work is using useState() hook with our input field. It’s also widely suggested in tutorials around the web.

method 1 with useState():

const [inputState, setInputState] = useState('');
const [people, setPeople] = useState([]);

const onChange = (event) => {
  setInputState(event.target.value)
}

const onSubmit = (e) => {
  e.preventDefault()
  setPeople([...people, inputState])
  setInputState('')   // pay extra attention to this line
}
// ...

<form onSubmit={onSubmit}>
  <input onChange={onChange} value={inputState} />
</form>

//...

Looks simple enough. We have inputState, that is up-to-date with input field because of onChange function. However (!!!), in this video about common react-hook mistakes, Kyle points, that this method isn’t the optimal one, cause it makes the whole page re-render every time we change input value. So, he suggests using useRef() hook instead.

*method 2 with useRef():*

const [people, setPeople] = useState([]);
const inputRef = useRef([]);

const onSubmit = (e) => {
  e.preventDefault()
  setPeople([...people, inputRef.current.value])
  // inputRef.current.value = ''   <==  won't work
}
// ...

<form onSubmit={onSubmit}>
  <input ref={inputRef} />
</form>

//...

The second method works fine, and re-renders the page only once, when the submit event happens. However, we are going to submit this form multiple times, so we want onSubmit function to clear the input value. If we try adding inputRef.current.value = ''; in the end of onSubmit function, it breaks our app. The reason must be that setting state is asynchronous, so it ends up with updating state after making input value empty. To resolve it we can use another hook, useEffect(), which will clear our input value only after our stateful element is updated

method 2 updated with useEffect():

const [people, setPeople] = useState([]);
const inputRef = useRef([]);

useEffect(() => inputRef.current.value = '', [people])

const onSubmit = (e) => {
  e.preventDefault()
  setPeople([...people, inputRef.current.value])
}
// ...

<form onSubmit={onSubmit}>
  <input ref={inputRef} />
</form>

//...

Finally. What’s the question??

We have these two methods:

  • First one is intuitive, using simple mechanics, using just one hook, BUT re-rendering the page multiple times.

  • Second one uses as much as three different hooks, more complex mechanics, BUT re-renders only on submit.

Which should I use? Which could be considered the correct one? Or maybe I’m missing something and the answer is ‘neither’?

Some similar questions here discuss the differences, but as we are already aware of differences, what to choose?

If your form doesn’t have validation, you can use useRef.

But should I? Does this stack of hooks really improve the performance?

I’d appreciate your thoughts and suggestions!

3

Answers


  1. The choice between the two methods depends on your specific use case and your priorities for your application.

    If re-rendering the page multiple times is not a performance concern for your application and you prefer a simpler, more intuitive code, then the first method may be a good choice.

    On the other hand, if you want to optimize performance and reduce unnecessary re-renders, then the second method may be a better choice, even though it is more complex.

    It’s also worth noting that the second method may be more suitable for larger and more complex forms that have multiple input fields and complex validation rules, while the first method may be sufficient for smaller and simpler forms.

    Ultimately, there is no one "correct" method, as both have their advantages and disadvantages. You should choose the method that best fits your specific use case and your priorities for your application, whether it be simplicity, performance, or scalability.

    Login or Signup to reply.
  2. I haven’t watched the video, but if the author suggests to use useRef() instead of state to save performance, he doesn’t seem to have much clue of how React actually works.

    React only applies changes to the DOM when it spots the changes in the virtual DOM, which is the representation of the nodes used to keep track of necessary changes. If your state change causes many DOM updates, it means that you do it wrong, most likely recreate a state value unnecessarily. The easiest way to this mistake is to recreate object in state, instead of memoizing it.

    Using states means achieving much cleaner and reusable React code. Use useRef() only when you need to perform an action on a DOM element (like focus()).

    Login or Signup to reply.
  3. We have had issues with performance on large forms (forms with lots of inputs) and using state. While a simple state update is not much of a performance hit, if there are fields that update depending on that state, there may be a large performance hit, as there was in our case.

    Our solution was to move to react hook form. While this may not answer your question directly, this is the direction we ended up going to solve issues that using state on the form caused and not to go down the slightly messy useRef path.

    You also get some great methods like isDirty and isValid to help in form submission. You can also clear the form relatively easy with the reset method.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search