useLocal: the useState hook for a properly-synced state

As you might know, the React hook useState takes one argument, which will initialize its internal state to that given value. When React 16 with Hooks got released, I found it a little bit confusing, but it perfectly makes sense.

No matter what, there are still situations, where you need to update the state based on the incoming props. Usually that is done using a useEffect hook, where you listen on the incoming prop to change, and then update your local state.

This is a great way of handling it, because you, as the owner of the component can perfectly control, if the parent prop change is actually what you want. It could even break your component if the parent decides to update a prop during a critical state of your component.

But there are also situations, where not much can happen. There are simple scenarios where you basically want to hold a local version and not propagate it up the tree until a certain condition happen. During that time, you still want to allow the parent controlling component to update the local value, if that is what it wants.

Here is an example how to allow the parent controlling component set (and update, if necessary) the from and to values. It can happen that for example for whatever reason, there is another component, that can set a date range, for that, we would want that from and to can be updated.

const RangeDatepicker = ({ value: { from, to }, onChange }) => {
   const [from, setFrom] = useLocal(from)
   const [to, setTo] = useLocal(to)
   const update = () => {
    if (from && to) {
      onChange({ from, to });
    }
   }

   useEffect(update, [from, to])

   return <MyCalendarRangePicker from={from} to={to} onChangeFrom={setFrom} onChangeTo={setTo} />
}

the easiest implementation of such a hook (in Typscript) looks like this

One further improvement would be, to pass in some conditional function that checks, if it is allowed to update the local state.

You can visit the gist here

34