Just Use HTML

2 hours ago 1

I’ve worked on so many projects recently that were more complicated than they needed to be because they used JavaScript to generate HTML.

JavaScript is…

  • Slower to load
  • Slower to run
  • More prone to breaking
  • Harder to read and reason about
  • Doesn’t actually look like the final output

It’s inferior to just using HTML in nearly every way.

I’m not saying never use JavaScript, though. I think JS is great at augmenting and enhancing what’s already there, and adding interactivity that cannot (yet) but handled with HTML.

Let’s look at two examples…

Submitting a form

I see this a lot in React and JSX.

Every input in a form has an input listener on it. Any changes to that input update a state property. That property is used to set the value of the input, creating this weird circular logic.

(This approach is called “controlled inputs” in React-land, and some devs are slowly moving away from it, finally.)

The form submit is often also tied to clicking a <button> rather than submitting a form, meaning that hitting enter on an input won’t submit the form. This removes a native accessibility feature.

function Login () { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); function handleSubmit () { if (!username || !password) { // Show error message return; } fetch('/login', { method: 'POST', body: JSON.stringify({ username, password }), }); } return ( <form onSubmit={event => event.preventDefault()}> <label for="username">Username</label> <input id="username" type="text" onInput={event => setUsername(event.value)} value={username} /> <label for="password">Password</label> <input id="password" type="password" onInput={event => setPassword(event.value)} value={password} /> <button onClick={handleSubmit}>Submit</button> </form> ); }

Here’s that same setup with HTML…

<form action="/login" method="POST"> <label for="username">Username</label> <input id="username" type="text" required /> <label for="password">Password</label> <input id="password" type="password" required /> <button>Submit</button> </form>

And then you can enhance it with just a touch of JavaScript…

const form = document.querySelector('[action*="/login"]'); form.addEventListener('submit', event => { event.preventDefault(); const data = new FormData(form); const body = JSON.stringify(Object.fromEntries(data)); fetch('/login', { method: 'POST', body }); });

Hell, you can even do this in React if you want!

function Login () { function handleSubmit (event) { event.preventDefault(); const data = new FormData(event.target); const body = JSON.stringify(Object.fromEntries(data)); fetch('/login', { method: 'POST', body }); } return ( <form onSubmit={handleSubmit}> <label for="username">Username</label> <input id="username" type="text" required /> <label for="password">Password</label> <input id="password" type="password" required /> <button>Submit</button> </form> ); }

API responses

Another area where you can lean a lot more heavily on HTML is API responses.

Let’s say you have a <table> that gets generated based on some data that’s specific to the user or some selections that have been made in a <form>.

In most modern apps, that means getting back some JSON, and generating a <table> from it.

const app = document.querySelector('#app'); const request = await fetch('/my-wizards'); const response = await request.json(); app.innerHTML = `<table> <thead> <tr> <th>Name</th> <th>Location</th> <th>Powers</th> </tr> </thead> <tbody> ${response.wizards.map(wizard => { const {name, location, powers} = wizard; const row = `<tr> <td>${name}</td> <td>${location}</td> <td>${powers}</td> </tr>`; return row; }).join('')} </tbody> </table>`;

But if a server has to do the work of getting that information and sending it back to you anyways, it could also just send the <table> HTML, which you could then render into the UI.

const app = document.querySelector('#app'); const request = await fetch('/my-wizards'); const response = await request.text(); app.innerHTML = response;

There are workflow changes

This, of course, changes the workflow of building apps quite a bit.

A lot of work shifts to the backend that in today’s apps is handled with client-side code. But… that’s a good thing?

It means faster, simpler apps that behave more predictably and reliably.

Read Entire Article