E se desse pra executar React diretamente no navegador?
Eu entrei numa "pira" no final de semana passada pensando no porquê não temos uma lib (ou qualquer outro jeito) de rodar um código React-Like direto no navegador.
Eu sei que tem o JSX pra ser compilado em JavaScript corretamente, toda a lógica de reatividade e do Virtual DOM. Mas o meu ponto aqui é: projetos estáticos, ou construídos em outra linguagem como PHP, poderiam ter pequenas partes interativas com React (mas isso necessita de um monte de configurações/processos para implementar).
O ponto em questão que eu tento trazer, é da complexidade que existe pra criar um código que faz um fetch e renderiza uma lista de elementos na tela com VanillaJS do que com React (que torna esse tipo de tarefa extremamente simples).
Então como um desafio, eu criei uma lib com VanillaJS que permite escrever codigos React-Like usando Template Literals + Custom Elements no lugar do JSX.
To trazendo esse projeto aqui pra entender se vocês veem valor num projeto como esse, e apontarem onde eu cometi erros ao tentar recriar essas principais features do React nessa lib.
O repo do projeto tá aqui: https://github.com/discovery-solutions/react.
E um exemplo de como um código pra listar uma lista de posts ficaria utilizando ela:
Arquivo index.html
:
<!DOCTYPE html>
<html>
<head>
<title>React by DSCVR Solutions</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<script src="index.js" type="module" defer></script>
</head>
<body>
<my-app></my-app>
</body>
</html>
Arquivo index.js
:
import { register, render, useEffect, useState } from "https://cdn.jsdelivr.net/gh/discovery-solutions/react@master/dist/index.es.js";
const POSTS_API = "https://jsonplaceholder.typicode.com/posts";
function App() {
const [ posts, setPosts ] = useState([]);
const fetchPosts = async () => {
try {
const raw = await fetch(POSTS_API);
const res = await raw.json();
setPosts(res);
} catch (e) {
console.log(e);
alert(e.message);
}
}
useEffect(() => {
fetchPosts();
}, []);
return render`
<div class="grid grid-cols-8 gap-4">
${ posts.slice(0, 10).map(post => render`
<div class="bg-slate-300 p-2 rounded">
<h3 class="text-lg font-bold">${post.title}</h3>
<p>${post.body.slice(0, 100)}</p>
</div>
`)}
</div>
`;
}
export default register(App, "my-app");