3

React Hook Forms provides a method append() on useFieldArray to add more rows to the dynamic fields array.

I'm able to use append(). However, I want to execute another function immediately after calling append(). But that's not happening. Instead, the next function gets called before append() is completed.

How can I change this behavour and ensure that the next function will be called only after append() is completed?

https://react-hook-form.com/api/usefieldarray

In the following example:

onClick={() => {
                    console.log('fields 1', fields)
                    append({
                      item: 
                        {
                          id: 1, 
                          name: 'test'
                        }
                    });
                    console.log('fields 2', fields)

                    }}>

In the above example, the length of fields remains the same. It doesn't increase. How do I resolve this?

asanas
  • 3,782
  • 11
  • 43
  • 72

1 Answers1

1

Under the hood, append relies on a call to a useState setter (see the source), which means that fields is a useState stateful value and you'll only see the updated value on the next render.

To perform effects in response to state changes, use the useEffect hook. You can read more about it here. In your case, you'd want to do something like

import React, { useEffect } from 'react';
import { useFieldArray } from 'react-hook-form';

const MyComponent = () => {
  const { fields, append } = useFieldArray(...);

  useEffect(() => {
    // this callback will run once on initial render and
    // then again whenever `fields` is updated
    console.log('fields 2', fields);
  }, [fields]);

  return (
    <div>
      <button onClick={() => {
          console.log('fields 1', fields);
          append({ item: { id: 1, name: 'test' } });
        }}>
        Click me
      </button>
    </div>
  );
};

In the above example, the component will print

fields 2 []

on initial render, and then

fields 1 []
fields 2 [{ id: 1, name: 'test' }]

once you click the button to append a new field. If you need to differentiate between initial render and subsequent updates, you can check that the value of fields has changed from its initial value (probably []).

superhawk610
  • 2,457
  • 2
  • 18
  • 27
  • 1
    Thanks. This is really helpful. But the useEffect be called for any change in fields, even if user updates value in a field in the form? What if I wanted to make it run only when a new object is added fields and not otherwise. Is that possible? – asanas May 05 '21 at 17:21
  • Actually I tried and it updates only when a new object is added to array. So, it works well for me. But just want to make sure that this indeed is how it will work. – asanas May 05 '21 at 17:30
  • Also, is it possible to not make it run on initial render? – asanas May 05 '21 at 17:33
  • 1
    You're correct, it will only run when the external shape of `fields` changes (when an element is added or removed), not when a field's value is modified. If you want to avoid the run on initial render, you can track whether or not you've rendered in a ref and conditionally run based on that (see [this SO answer](https://stackoverflow.com/a/53254028/885098)). – superhawk610 May 05 '21 at 18:26