Forms are useful. They allow us to pass data to a website. We see them everywhere, signup forms, contact forms, and in a million other ways. They are an html way to communicate with other html pages over HTTP.
You can see how your document tries to communicate with itself with this simple and ugly form.
<form> <input name='submission' type='text'> <input type='submit'> </form>
If I type the word 'something' then press submit, I get this:
My URL is updating on form submission! In technical terms, my form is submitting a GET request with the query parameter "submission" set to "something" to the server. This is great for dumb pages or server side rendered applications, but we frontend developers love to handle state on the browser. We could be having state that needs to be persistent, and refreshing the page is unacceptable. (think of a modal popup window with a form, you don't want to refresh the page and make the user re-open it).
So why does the browser refresh happen? Basically, forms in the browser want to pass data to a page. When you submit a form, it redirects you to the page that you submitted the data to. If you don't supply an action attribute to the form, or a method it will submit it to your current page using a GET parameter like we showed above.
so the HTML code above is doing the same as this.
<form action="/" method="GET"> <input name='submission' type='text'> <input type='submit'> </form>
The form [action="/"] attribute is telling the browser that we want to post the data to the root URL of the website. The method is expecting an HTTP verb (POST, PUT, PATCH, DELETE, etc...) but GET is the default one. GET requests are appended to the url as shown in the image above. This is handy, but often you don't want that because you don't need that information in your browser history for everyone to see.
<form action="/" method="GET" onsubmit="event.preventDefault()"> <input name='submission' type='text'> <input type='submit'> </form>
If you run test again, you no longer get a query string in the URL and your state persists!
You are preventing the browser from doing what it does whenever it sees a form element.
<form> <input name='submission' type='text'> <input type='submit'> </form> <script> document.querySelector("form").addEventListener("submit", (event) => event.preventDefault()); </script>
Ahh much nicer, we took away the native properties of the form element and told the browser, we'll take it from here. Now we can decide exactly how we want the form to behave.
So the more adept programmer might say something along the lines of 'if I have to jump through hoops when I put a form element on the page, can't I just omit it altogether?'. And yes, they would be right that they could do the same as the example above only using an input element and a button. However, forms are the 'semantic' way of writing html, which is useful especially for screen readers. Screen readers are all programmed to react predictably to a form element, but if you don't group the functionality of an input with a submit, you'll have to keep track of all that yourself through adding labels and grouping the behavior together. This is possible, but it is not recommended because it introduces more surface area for mistakes appear.
So there you have it. Hopefully this helps if you are wondering why you are losing the state of the application every time you hit submit on your forms. Stay tuned for more tips and tricks!