Apenas uma palavra: Produtividade.
Vou dar um exemplo, quando você inicia um projeto com react, seja com vite ou CRA (com next é diferente), o script que inicia o projeto já nos dá uma página rodando, como essa:
Essa página é gerada pelo seguinte componente React:
//App.tsx
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<div className="App">
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://reactjs.org" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</div>
)
}
export default App
Mas e se formos fazer essa mesma página em html e javascript vanilla?
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="stylesheet" href="./App.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div className="App">
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" className="logo" alt="Vite logo" />
</a>
<a href="https://reactjs.org" target="_blank">
<img src="./assets/react.svg" className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick="handleClick()">
count is <span id="count">1<span>
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</div>
<script>
const countElement = document.getElementById('count') // ou document.querySelector('#count')
const handleClick = () => {
const value = parseInt(countElement.textContent)
countElement.textContent = `${++value}`
}
</script>
</body>
</html>
Veja que inicialmente nem parece ter muita diferança, mas já existe uma complexidade e verbosidade muito maior no segundo exemplo. A grande vantagem de usar um framework é que ele abstrai e faz muitas coisas para você. No caso do React temos a facilidade de componentizar todos os elementos html que julgarmos necessários e assim reutilizá-los. Quando olhamos para aplicações simples nos parece que apenas dificulta, mas ao vermos projetos maiores, manter com html, css e javascript na raça é totalmente inviável, pois será impossível fazer uma manutenção efetiva nesse tipo de código, devido a complexidade elevada.
O que muitas vezes um simples useState resolve, seria necessárias dezenas de linhas em javascript vanilla para ter o mesmo efeito. Esses são alguns motivos pela qual essas bibliotecas e frameworks existem, poderia citar muito mais, mas essas são as mais importantes.