Simple Blog Post Editor

Create a text input area where users can enter a title and content for a blog post, and submit it with a button.

Solution

Explanation

The HTML Structure

A form element with an onSubmit that calls handleSubmit.

Note there are labels and inputs. Reminder that it is the id attribute that links to the label via htmlFor. The name attribute is the key for the value when the form data is received.

Each input is linked to a separate onChange function. The final input has a type of submit.

onChange functions

Each on change function is connected with its relevant state. Each function updates state.

handleSubmit function

The default behaviour of a JS Form element is to send the data and refresh the page. To stop that from happening, we use event.preventDefault.

The data is then be processed. In this case, an alert has been created.

Notice that both the title and content are reset to a blank string afterwards.

Code

import { ChangeEvent, FormEvent, useState } from "react";
import styles from "./Solution.module.css";

const Solution = () => {
  const [title, setTitle] = useState<string>("");
  const [content, setContent] = useState<string>("");

  function handleTitle(event: ChangeEvent<HTMLInputElement>): void {
    setTitle(event.target.value);
  }

  function handleContent(event: ChangeEvent<HTMLTextAreaElement>): void {
    setContent(event.target.value);
  }

  function handleSubmit(event: FormEvent<HTMLFormElement>): void {
    event.preventDefault();

    alert(`Title: ${title}, \nContent: ${content}`);
    setTitle("");
    setContent("");
  }

  return (
    <form onSubmit={handleSubmit} className={styles.container}>
      <label className={styles.label} htmlFor="title">
        Title
      </label>
      <input
        required
        onChange={handleTitle}
        value={title}
        className={styles.input}
        type="text"
        name="title"
        id="title"
      />
      <label className={styles.label} htmlFor="content">
        Content
      </label>
      <textarea
        required
        onChange={handleContent}
        value={content}
        rows={5}
        className={styles.input}
        name="content"
        id="content"
      />
      <input
        aria-label="Submit post"
        className={styles.button}
        type="submit"
        value="Post"
      />
    </form>
  );
};

export default Solution;

Styling

.container {
  display: flex;
  flex-direction: column;
  max-width: 350px;
  border: 1px solid black;
  padding: 15px;
  gap: 15px;
}

.label {
  display: block;
}

.input {
  padding: 5px;
}

.button {
  padding: 5px;
  cursor: pointer;
}

Links