Introducing Object Hooks: Mutable State for React 🤯

Ryan Kahn (he/him) - Apr 21 '20 - - Dev Community

The idea I started with is: What if we could write state changes in react as mutations on a persistent reference? 🤔 So I wrote the code to make it work! The basic concept is summed up in the code from the banner image:

import React from 'react';

import { useObject } from '../hooks/useObject';

export const Counter: React.FC = () => {
  const [state] = useObject({
    count: 1,
  });

  return (
    <button
      onClick={() => {
        state.count++;
      }}
    >
      {state.count}
    </button>
  );
};
Enter fullscreen mode Exit fullscreen mode

In this case, state is a persistent reference that you can mutate (state.count++). The consequences of this change are fairly interesting. For one, you can create these objects with a class! So the above example could be rewritten as:

import React from 'react';

import { useInstance } from '../hooks/useInstance';

class Counter {
  count = 1;

  increment() {
    this.count++;
  }
}

export const Counter: React.FC = () => {
  const [counter] = useInstance(Counter);

  return (
    <button
      onClick={() => {
        counter.increment();
      }}
    >
      {counter.count}
    </button>
  );
};
Enter fullscreen mode Exit fullscreen mode

Also, if you need to subscribe to to changes in the objects outside of a component function, they implement the AsyncIterable interface, so you can await their next state, or for await future states in an async function. Here's a logger class that subscribes to a counter!

class CounterLogger {
  constructor(
    private counter: Counter & AsyncIterable<Counter>
  ) {}

  log(count: number) {
    console.log(`Count is: ${count}`);
  }

  async watch() {
    this.log(this.counter.count);

    for await (const { count } of this.counter) {
      this.log(count);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

There's more to it, and there will be more as the project progresses. I wanted to share what I have in its current "state" 😉 to give everyone a chance to contribute their thoughts and ideas! If you're interested, clone the repo and try it for yourself! Or leave a comment or question on this post! All are contributions, all are welcome. 🔰

. . . . . . . . . . . . . . . . . . . .
Terabox Video Player