Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

361
Vistas
useState polyfill, is this correct?

Trying to write a custom implementation of useState. Let's say only for a single value.

function useMyState(initVal){
  const obj = {
    value: initVal,
    get stateValGet() {
      return this.value
    },
    set stateValSet(val) {
      this.value = val
    }
  };
  const setVal = (val) => {
    obj.stateValSet = val
  }
  return [obj.stateValGet, setVal]
}

Doesn't seem to work though, can anyone tell why? Unable to crack this.

It returns this [, <function_setter>] So if you try to run this setVal method, it does trigger the setter. But getter never gets called upon the updation.

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

Every state manager that wants to interact with React has to find a way to connect to React lifecycle, in order to be able to trigger re-renders on state change. useState hook internally uses useReducer : https://github.com/facebook/react/blob/16.8.6/packages/react-dom/src/server/ReactPartialRendererHooks.js#L254

That's why I made this naive implementation of useState based on JS Proxies and a useReducer dummy dispatch just to force a re-render when state changes.

It's naive, but that's what valtio is based on.

Consider that the power of proxies would make it possible to trigger re-renders by mutating state directly, that's what happens in valtio !

import { useReducer, useCallback, useMemo } from 'react';

export const useMyState = (_state) => {
  // FORCE RERENDER
  const [, rerender] = useReducer(() => ({}));
  const forceUpdate = useCallback(() => rerender({}), []);

  // INITIALIZE STATE AS A MEMOIZED PROXY
  const { proxy, set } = useMemo(() => {
    const target = {
      state: _state,
    };
    // Place a trap on setter, to trigger a component rerender
    const handler = {
      set(target, prop, value) {
        console.log('SETTING', target, prop, value);
        target[prop] = value;
        forceUpdate();
        return true;
      },
    };

    const proxy = new Proxy(target, handler);

    const set = (d) => {
      const value = typeof d === 'function' ? d(proxy.state) : d;
      if (value !== proxy.state) proxy.state = value;
    };

    return { proxy, set };
  }, []);

  return [proxy.state, set];
};

Demo https://stackblitz.com/edit/react-33fpbk?file=src%2FApp.js

about 4 years ago · Juan Pablo Isaza Denunciar

0

useState's functionality can't really be polyfilled or substituted with your own custom implementation, because it not only stores state, but it also triggers a component re-render when the state setter is called. Triggering such a re-render is only possible with access to React internals, which the surface API available to us doesn't have access to.

useState can't be replaced with your own implementation unless that implementation also uses useState itself in order to get the component it's used in to re-render when the state setter is called.

You could create your own custom implementation outside of React, though, one which simulates a re-render by calling a function again when the state setter is called.

const render = () => {
  console.log('rendering');
  const [value, setValue] = useMyState(0);
  document.querySelector('.root').textContent = value;
  const button = document.querySelector('.root')
    .appendChild(document.createElement('button'));
  button.addEventListener('click', () => setValue(value + 1));
  button.textContent = 'increment';
};
const useMyState = (() => {
  let mounted = false;
  let currentState;
  return (initialValue) => {
    if (!mounted) {
      mounted = true;
      currentState = initialValue;
    }
    return [
      currentState,
      (newState) => {
        currentState = newState;
        render();
      }
    ];
  };
})();
render();
<div class="root"></div>

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda