SFernando
SFernando

Reputation: 1124

Custom hook reset to its initial state

Hook

export const useCreateAccount = () => {
  const [state, setState] = useState(initialState)

  const onChangeInput: ChangeEventFunction = useCallback(({ target }) => {
    if (!target.files) {
      return setState({ ...state, [target.name]: target.value })
    }
    setState({ ...state, [target.name]: target.files[0] })
  }, [])


  return { onChangeInput }
}

Component

const { onChangeInput } = useCreateAccount()

<form>
 <input name="name1" onChange={onChangeInput}>
 <input name="name2" onChange={onChangeInput}>
</form>

Every time I do some change in second input(name2) the previous state(name1) of the component has been lost(reset to initial state), The reason I use 'useCallback', I only need one instance of 'onChangeInput'

But if I remove 'useCallback', state is keeping the previous values(name1)

I can't understand this behavior in hooks, can someone elaborate more on this?

Upvotes: 2

Views: 1800

Answers (1)

Agney
Agney

Reputation: 19194

From the docs:

Any function inside a component, including event handlers and effects, “sees” the props and state from the render it was created in.

Here, when you are using useCallback, the function has been defined in it's initial render and has the initial state defined then. This is the reason why useCallback has a depedency array that can be used to refresh the function and values used inside it.

But you cannot use state as a dependency because you are setting the same inside it, instead you can use the functional version of setState so as to get the previous values of state instead of reffering to the central one.

const onChangeInput: ChangeEventFunction = useCallback(({ target }) => {
    if (!target.files) {
      return setState(prevState => ({ ...prevState, [target.name]: target.value }));
    }
    setState(prevState => ({ ...prevState, [target.name]: target.files[0] }))
}, [])

Upvotes: 1

Related Questions