Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

356
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda