11. Use Forms To Add An Item#

11.1. Add The Form#

To be able to add FAQ items to the list, we will start by adding an add form:

23return (
24    <div>
25      <ul>
26        {faqList.map((item, index) => (
27          <FaqItem
28            key={index}
29            question={item.question}
30            answer={item.answer}
31            index={index}
32            onDelete={onDelete}
33          />
34        ))}
35      </ul>
36      <form>
37        <label>
38          Question: <input name="question" type="text" />
39        </label>
40        <label>
41          Answer: <textarea name="answer" />
42        </label>
43        <input type="submit" value="Add" />
44      </form>
45    </div>
46  );
Differences
--- a/src/App.js
+++ b/src/App.js
@@ -21,17 +21,28 @@ function App() {
   };

   return (
-    <ul>
-      {faqList.map((item, index) => (
-        <FaqItem
-          key={index}
-          question={item.question}
-          answer={item.answer}
-          index={index}
-          onDelete={onDelete}
-        />
-      ))}
-    </ul>
+    <div>
+      <ul>
+        {faqList.map((item, index) => (
+          <FaqItem
+            key={index}
+            question={item.question}
+            answer={item.answer}
+            index={index}
+            onDelete={onDelete}
+          />
+        ))}
+      </ul>
+      <form>
+        <label>
+          Question: <input name="question" type="text" />
+        </label>
+        <label>
+          Answer: <textarea name="answer" />
+        </label>
+        <input type="submit" value="Add" />
+      </form>
+    </div>
   );
 }

11.2. Manage Field Values In The State#

To manage the values of the fields in the form, we will use the state. Add a question and answer value to the state which contains the values of the inputs. Add onChange handlers to the input and textarea which will change the values in the state when the input changes. This pattern is called "controlled inputs".

Solution
 1import { useState } from "react";
 2import "./App.css";
 3import FaqItem from "./components/FaqItem";
 4
 5function App() {
 6  const [faqList, setFaqList] = useState([
 7    {
 8      question: "What does the Plone Foundation do?",
 9      answer: "The mission of the Plone Foundation is to protect and...",
10    },
11    {
12      question: "Why does Plone need a Foundation?",
13      answer: "Plone has reached critical mass, with enterprise...",
14    },
15  ]);
16
17  const [question, setQuestion] = useState("");
18  const [answer, setAnswer] = useState("");
19
20  const onDelete = (index) => {
21    let faq = [...faqList];
22    faq.splice(index, 1);
23    setFaqList(faq);
24  };
25
26  const onChangeAnswer = (e) => {
27    setAnswer(e.target.value);
28  };
29
30  const onChangeQuestion = (e) => {
31    setQuestion(e.target.value);
32  };
33
34  return (
35    <div>
36      <ul>
37        {faqList.map((item, index) => (
38          <FaqItem
39            key={index}
40            question={item.question}
41            answer={item.answer}
42            index={index}
43            onDelete={onDelete}
44          />
45        ))}
46      </ul>
47      <form>
48        <label>
49          Question:{" "}
50          <input
51            name="question"
52            type="text"
53            value={question}
54            onChange={onChangeQuestion}
55          />
56        </label>
57        <label>
58          Answer:{" "}
59          <textarea name="answer" value={answer} onChange={onChangeAnswer} />
60        </label>
61        <input type="submit" value="Add" />
62      </form>
63    </div>
64  );
65}
66
67export default App;
--- a/src/App.js
+++ b/src/App.js
@@ -14,12 +14,23 @@ function App() {
     },
   ]);

+  const [question, setQuestion] = useState("");
+  const [answer, setAnswer] = useState("");
+
   const onDelete = (index) => {
     let faq = [...faqList];
     faq.splice(index, 1);
     setFaqList(faq);
   };

+  const onChangeAnswer = (e) => {
+    setAnswer(e.target.value);
+  };
+
+  const onChangeQuestion = (e) => {
+    setQuestion(e.target.value);
+  };
+
   return (
     <div>
       <ul>
@@ -35,10 +46,17 @@ function App() {
       </ul>
       <form>
         <label>
-          Question: <input name="question" type="text" />
+          Question:{" "}
+          <input
+            name="question"
+            type="text"
+            value={question}
+            onChange={onChangeQuestion}
+          />
         </label>
         <label>
-          Answer: <textarea name="answer" />
+          Answer:{" "}
+          <textarea name="answer" value={answer} onChange={onChangeAnswer} />
         </label>
         <input type="submit" value="Add" />
       </form>

11.3. Submit Handler#

Now that our values are managed in the state, we can write our submit handler. Write an onSubmit handler which reads the values from the state and adds the new FAQ item to the list. After the item is added, the inputs should also reset to empty values.

Solution

And add this to the body of the function.

34  const onSubmit = (e) => {
35    e.preventDefault();
36    setFaqList([...faqList, { question, answer }]);
37    setQuestion("");
38    setAnswer("");
39  };
40
41  return (
42    <div>
43      <ul>
44        {faqList.map((item, index) => (
45          <FaqItem
46            key={index}
47            question={item.question}
48            answer={item.answer}
49            index={index}
50            onDelete={onDelete}
51          />
52        ))}
53      </ul>
54      <form onSubmit={onSubmit}>
55        <label>
56          Question:{" "}
57          <input
58            name="question"
59            type="text"
60            value={question}
61            onChange={onChangeQuestion}
62          />
63        </label>
64        <label>
65          Answer:{" "}
66          <textarea name="answer" value={answer} onChange={onChangeAnswer} />
67        </label>
68        <input type="submit" value="Add" />
69      </form>
70    </div>
71  );
72}
--- a/src/App.js
+++ b/src/App.js
@@ -31,6 +31,13 @@ function App() {
     setQuestion(e.target.value);
   };

+  const onSubmit = (e) => {
+    e.preventDefault();
+    setFaqList([...faqList, { question, answer }]);
+    setQuestion("");
+    setAnswer("");
+  };
+
   return (
     <div>
       <ul>
@@ -44,7 +51,7 @@ function App() {
           />
         ))}
       </ul>
-      <form>
+      <form onSubmit={onSubmit}>
         <label>
           Question:{" "}
           <input