Metaprogramação com React
O objetivo não é entrar em detalhes sobre o que é metaprogramação e suas técnicas, mas apenas ver um exemplo de como aplicá-la no React.
Este é meu primeiro post neste meio fantástico, e gostaria de escrever um pouco sobre uma técnica que já usamos uma vez na vida (de um programador), mas que talvez não conheçamos em detalhes, a metaprogramação !
O código abaixo é um exemplo de como usar a construção Proxy e a API Reflect , dentro de um componente React. O componente MyComponent usa o estado local do React ( useState ) para gerenciar um objeto proxyData que tem uma propriedade “ test ” inicialmente vazia. O componente possui três botões que, ao serem clicados, modificam a propriedade “teste” do objeto proxyData .
import React, { useState } from 'react';
function MyComponent() {
const [proxyData, setProxyData] = useState({ test: '' });
const [render, setRender] = useState(false);
const handleClickMemo = React.useCallback(() => {
const updatedData = new Proxy(proxyData, {
set(target, prop, value) {
const success = Reflect.set(target, prop, value);
if (success) {
console.log(`Prop ${prop} modified with value ${value}`);
}
return success;
},
});
updatedData.test = crypto.randomUUID();
setProxyData(updatedData);
}, []);
// without useCallback, do new proxy every time
const handleClick = () => {
const updatedData = new Proxy(proxyData, {
set(target, prop, value) {
const success = Reflect.set(target, prop, value);
if (success) {
console.warn(`Prop ${prop} modified with value ${value}`);
}
return success;
},
});
updatedData.test = crypto.randomUUID();
setProxyData(updatedData);
};
// case where react doesn't render, but in console,
// if it is a proxy the object is updated
// BE CAREFUL when using proxies
const handleClickNoRender = () => {
proxyData.test = crypto.randomUUID();
setProxyData(proxyData);
};
return (
<div>
<pre>{JSON.stringify(proxyData)}</pre>
<button onClick={handleClickMemo}>handleClickMemo</button>
<button onClick={handleClick}>handleClick</button>
<button onClick={handleClickNoRender}>handleClickNoRender</button>
<br />
<button onClick={() => setRender(!render)}>re-render</button>
</div>
);
}
export default function App() {
return <MyComponent />;
}
O primeiro botão, handleClickMemo , usa a função React.useCallback para criar uma função que é armazenada em cache pelo React. Isso é útil para evitar que a função seja reconstruída toda vez que o componente for atualizado. A função cria um novo objeto Proxy com base no objeto proxyData , atualiza a propriedade “test” com um novo valor gerado aleatoriamente e define o estado de proxyData com o objeto recém-criado.
const handleClickMemo = React.useCallback(() => {
const updatedData = new Proxy(proxyData, {
set(target, prop, value) {
const success = Reflect.set(target, prop, value);
if (success) {
console.log(`Prop ${prop} modified with value ${value}`);
}
return success;
},
});
updatedData.test = crypto.randomUUID();
setProxyData(updatedData);
}, []);
// without useCallback, do new proxy every time
const handleClick = () => {
const updatedData = new Proxy(proxyData, {
set(target, prop, value) {
const success = Reflect.set(target, prop, value);
if (success) {
console.warn(`Prop ${prop} modified with value ${value}`);
}
return success;
},
});
updatedData.test = crypto.randomUUID();
setProxyData(updatedData);
};
// case where react doesn't render, but in console,
// if it is a proxy the object is updated
// BE CAREFUL when using proxies
const handleClickNoRender = () => {
proxyData.test = crypto.randomUUID();
setProxyData(proxyData);
};
É importante observar que o uso de um proxy pode ter efeitos colaterais e causar problemas de desempenho se não for usado corretamente. Além disso, a atualização de estados por meio de um objeto Proxy pode não ser detectada pelo React, portanto, deve-se ter cuidado ao usar Proxies em um componente React.
Neste link , você pode ver no console o comportamento de cada botão.





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)