DEV Community

Cover image for QWIK state management syntax for React with a custom hook. Alternative to setState.
Sourav
Sourav

Posted on

QWIK state management syntax for React with a custom hook. Alternative to setState.

Utilizing Javascript proxy this custom changes the default way of setting state in React which is a function that requires a function.
By using this hook simply assigning value to state will result same as setState. It’s really a wrapper around useState.

Here is usProxyState simple 20 lines of code.

https://github.com/Sourav9063/watchtogether/blob/master/src/helper/hooks/useProxyState.js

    import { useState } from "react";
    export const useProxyState = (initialState = {}) => {
      if (typeof initialState != "object") {
        initialState = { value: initialState };
      }
      const [state, setState] = useState(initialState);
      state.setState = setState;
      const handler = {
        set(_, prop, value) {
          if (value !== state[prop]) {
            setState((state) => {
              return { ...state, [prop]: value };
            });
          }
          return Reflect.set(...arguments);
        },
      };
      const stateProxy = new Proxy(state, handler);
      return stateProxy;
    };
Enter fullscreen mode Exit fullscreen mode

Notes

  • For Object type state, direct assignment will work i.e. state.count. Any other type state you can access and modify via state.value

  • You can get the default setState in state.setState()

    const state1 = useProxyState({ count: 1 });
    const state2 = useProxyState(1);
    //...
    state1.count = 100;
    state2.value = 200;
Enter fullscreen mode Exit fullscreen mode

Comparisons

useProxyState

    "use client";
    import { useProxyState } from "@/helper/hooks/useProxyState";
    import styles from "../page.module.css";
    export default function Personal() {
      const state1 = useProxyState({ count: 1 });// object
      const state2 = useProxyState(state1.count * 2);// not object

      state2.value = state1.count * 2; //no need for useEffect. And cannot be changed else where.
      return (
        <>
          <main className={styles.main}>
            <div className={styles["cards"]}>
              <button
                onClick={() => {
                  state1.count++; //simple assignment will update the state
                }}
              >{state1.count}
              </button>
              <button
                onClick={() => {
                  state2.value++;// for values other than object, use value.
                }}
              >{state2.value}
              </button>
            </div>
          </main>
        </>
      );
    }
Enter fullscreen mode Exit fullscreen mode

Default useState

    "use client";
    import styles from "../page.module.css";
    import { useEffect, useState } from "react";

    export default function Personal() {
      const [state3, setState3] = useState({
        count: 1,
      });
      const [state4, setState4] = useState(state3.count * 2);
      useEffect(() => {
        setState4(state3.count * 2);
        return () => {};
      }, [state3.count]);

      return (
        <>
          <main className={styles.main}>
            <div className={styles["cards"]}>
              <button
                onClick={() => {
                  setState3((state) => ({ ...state, count: state.count + 1 }));
                }}
              >
                useState {state3.count}
              </button>
              <button
                onClick={() => {
                  setState4((state) => {
                    return state + 1;
                  });
                }}
              >
                useState {state4}
              </button>
            </div>
          </main>
        </>
      );
    }
Enter fullscreen mode Exit fullscreen mode

Demo Source

GITHUB: sourav9063
WEBSITE: https://sourav9063.github.io/
LINKDIN: sourav-ahmed

Top comments (0)