coding

Como acessar o state do Redux de um build de produção do React 18

Solução atualizada para acessar o state do Redux em um build de produção com o React 18

Escrito em 21 de agosto de 2022 - 🕒 3 min. de leitura

Há alguns meses atrás, eu publiquei um post no meu blog sobre como acessar o state do Redux em um build de produção utilizando o console do navegador. No entanto, com o lançamento recente do React 18, essa técnica não funciona mais.

Neste blog post, vamos explorar o motivo pelo qual ela deixou de funcionar e como criar um script que ainda permita acessar o state do Redux em produção.

O que mudou?

No React 17, havia uma propriedade chamada _reactRootContainer no container do React, mas essa propriedade não existe mais no React 18. Em vez disso, como podemos ver no código-fonte do React, o container do React agora possui uma propriedade prefixada com __reactContainer e um número aleatório no final.

Para encontrar o container do React, podemos procurar por elementos DOM que possuem uma propriedade começando com __reactContainer. Primeiro, precisamos encontrar todos os elementos DOM que podem ser potencialmente o container do React.

A maioria dos aplicativos React usa um id HTML para definir o container e, em seguida, usa a função getElementById() para recuperá-lo. Portanto, para obter todos os elementos com um “id” no documento, podemos usar document.querySelectorAll("*[id ]").

Para encontrar todos os containers do React na página, podemos executar o seguinte script:

const internalRoots = Array.from(document.querySelectorAll("*[id]")).map((el) => {
    const key = Object.keys(el).filter((keyName) => keyName.includes('__reactContainer')).pop();

    return el[key];
}).filter((key) => key);

Pronto! Agora tudo o que temos a fazer é encontrar o _internalRoot e pronto, né? Né?!?!

Não

Na verdade, descobrir a primeira parte foi relativamente simples. Como não estou muito familiarizado com o código-fonte do React, tentei explorar todas as propriedades disponíveis do container, mas acabei optando pelo caminho mais fácil, ainda que preguiçoso.

Já que para obter o state do Redux usamos a função getState(), tudo o que precisamos fazer é percorrer a árvore de variáveis do container do React em busca dela.

Felizmente, já existe um Gist do GitHub para isso, então basta adaptá-lo para o nosso caso, examinando uma variável específica em vez da window.

const stores = new Set();
// code from https://gist.github.com/mindplay-dk/1843c267fc633688059dfa5e3b07d0dd
internalRoots.forEach((root) => {
    let seen = new Map();
    function search(obj) {
        if (seen.has(obj)) {
            return;
        }

        seen.set(obj, true);
        for (name in obj) {
            if (name === 'getState') {
                stores.add(obj);
            }

            if ((obj?.hasOwnProperty?.(name)) && (typeof obj[name] === "object") && (obj[name] != null)) {
                search(obj[name]);
            }
        }
    }

    search(root);
});

Pronto, e daí podemos acessar os states com [...stores].map((store) => store.getState()).

redux state on instagram

Você pode copiar e colar o script completo abaixo.

const internalRoots = Array.from(document.querySelectorAll("*[id]")).map((el) => {
    const key = Object.keys(el).filter((keyName) => keyName.includes('__reactContainer')).pop();

    return el[key];
}).filter((key) => key);

const stores = new Set();
// code from https://gist.github.com/mindplay-dk/1843c267fc633688059dfa5e3b07d0dd
internalRoots.forEach((root) => {
    let seen = new Map();
    function search(obj) {
        if (seen.has(obj)) {
            return;
        }

        seen.set(obj, true);
        for (name in obj) {
            if (name === 'getState') {
                stores.add(obj);
            }

            if ((obj?.hasOwnProperty?.(name)) && (typeof obj[name] === "object") && (obj[name] != null)) {
                search(obj[name]);
            }
        }
    }

    search(root);
});

[...stores].map((store) => store.getState());

Conclusão

Para concluir, neste post, exploramos o motivo pelo qual o método anterior para acessar o state do Redux em um build de produção deixou de funcionar no React 18 e apresentamos uma solução atualizada que permite acessar o state do Redux em produção.

Apesar de ter sido um desafio descobrir o novo método, com a ajuda de um script já existente e um pouco de adaptação, conseguimos encontrar uma solução viável.

Espero que este post tenha sido útil e que você consiga utilizá-lo em seus futuros projetos.

Tags:


Publicar um comentário

Comentários

Nenhum comentário.