DEV Community

Cédric Agoliki
Cédric Agoliki

Posted on

Better Alternatives to React's useState Hook

React's way to declare state is interesting, the useState Hook returns you an array of the state and a function to change the state.

The question is, how many times do you need those two elements seperately ?

I mean you always need both, you wouldn't declare the state only to have the setter function, or just the state itself without setter right? If no, why on earth would you do something like that?

Anyway, in this post I want to present two different way to declare the state: I call it the vue-like way and the solid-like way, just because they share some similarities.

The vue-like way

For this let's design the useBetterState() hook:

const useBetterState = (value) => {
  const [state, setState] = useState(value)
  return {
    get value() {
      return state
    },
    set value(v) {
      setState(v)
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now that it is defined, we can use it like this

const Counter = () => {
  const count = useBetterState(0)

  const increment = () => {
    count.value++
  }

  return (
    <>
      <div>{count.value}</div>
      <button onClick={increment}>+</button>
    </>
   )
}
Enter fullscreen mode Exit fullscreen mode

So much better Right ?

The solid-like way

I know solid also have a both the state and it's setter separately, but the similarity is in the use of a function to display the state.

const useSuperState = (value) => {
  const [state, setState] = useState(value)
  return function(v) {
    if (v != null) {
      setState(v)
    }
    return state
  }
}
Enter fullscreen mode Exit fullscreen mode

And we can use it this way:

const Counter = () => {
  const count = useSuperState(0)

  const increment = () => {
    count(count() + 1)
  }

  return (
    <>
      <div>{count()}</div>
      <button onClick={increment}>+</button>
    </>
   )
}
Enter fullscreen mode Exit fullscreen mode

As you can see, the whole idea of this experiment is to use one variable instead of two to manage a state.

Now before you scream blasphemy, remember this is just an experiment.
And before you write a comment think of me as a violent criminal who knows where you live lol :).

Let me know you thoughts though, I am really curious.

Top comments (4)

Collapse
 
dikamilo profile image
dikamilo

I mean you always need both, you wouldn't declare the state only to have the setter function, or just the state itself without setter right? If no, why on earth would you do something like that?

You not always need both ;) Sometimes you need to update "state" / have dynamic state based on other things and cause re-render/recalculate without manually set state. Recalculate each time component re-render can be expensive. A lot of devs use useState for this, ignoring setter, but this can be achieved by using useMemo as well:

const state = useMemo(() => {
   // some heavy calculation here ;)
   return (dep1 + dep 2) / 100
}, [dep1, dep2])
Enter fullscreen mode Exit fullscreen mode
Collapse
 
cedricagoliki profile image
Cédric Agoliki

You're right but I think that should be labelled bad practice. As you said, there is another and probably better way to do it. And useMemo() is definitely the way to go. So really you do not need to use useState() if it is only to use one of the elements. I think a normal variable can be used if there is no heavy calculation.

Collapse
 
yasminbelarma profile image
Yasmin Belarma

this is great!

Collapse
 
cedricagoliki profile image
Cédric Agoliki

Thanks!