Devahoy Logo
PublishedAt

React

พื้นฐาน React.js เรื่อง วิธีการจัดการ Form และ Input

พื้นฐาน React.js เรื่อง วิธีการจัดการ Form และ Input

วันนี้มาพบกับบทความเกี่ยวกับพื้นฐาน React.js ครับ ว่าด้วยเรื่องการของจัดการ Form และ Input ต่างๆ กันนะครับ

เนื่องจากว่าการทำ Web Application ปฎิเสธไม่ได้ว่า เราต้องใช้พวก Input Form ต่างๆ ในการส่งข้อมูลไปที่ Server ไม่ว่าจะเป็นการ POST/PUT/PATCH ด้วยการใช้ fetch หรือ Library อื่นๆ เช่น axios แต่ก่อนที่จะส่งละ เรามีวิธีการจัดการกับพวก state ของ Form ยังไงบ้าง ไปลองอ่านกันครับ

เริ่มต้นสร้าง Project

  • เราจะใช้ Create React App ขึ้นโปรเจ็ค และไม่ใช้ Library อื่นเลย
  • Component เราเป็นแบบ functional Component ฉะนั้นก็เลยใช้ Hook
  • เราจะใช้ useState() เพื่อเก็บ State ใน Component นะครับ

ผมสร้าง Project ขึ้นมาด้วย Create React App ครับ (หากใครที่หลงเข้ามาอ่าน ไม่มี Node.js ต้องทำการติดตั้งลงบนเครื่องก่อนนะครับ)

Terminal window
npx create-react-app basic-react-form

จากนั้น ผมเพิ่ม Bootstrap ไปซักนิด พอดีจะใช้ หน้า form ของ Bootstrap ก็เลยเพิ่มลงไปในไฟล์ public/index.html

1
<head>
2
<link
3
rel="stylesheet"
4
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
5
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
6
crossorigin="anonymous"
7
/>
8
<script
9
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
10
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
11
crossorigin="anonymous"
12
></script>
13
</head>

ลอง Start Server ก็ได้หน้า Create React App default ขึ้นมา

Terminal window
npm start

ต่อมา ลองเปลี่ยนส่วน App.js เป็น Form จาก Bootstrap

1
import React from 'react'
2
import './App.css'
3
4
function App() {
5
return (
6
<div className="container">
7
<div className="row mt-4">
8
<div className="col-12 col-md-6 offset-md-3">
9
<h2 className="my-4 text-center">LOGIN</h2>
10
11
<form>
12
<div className="form-group">
13
<label for="exampleInputEmail1">Email address</label>
14
<input
15
type="email"
16
className="form-control"
17
id="exampleInputEmail1"
18
aria-describedby="emailHelp"
19
placeholder="Enter email"
20
/>
21
</div>
22
<div className="form-group">
23
<label for="exampleInputPassword1">Password</label>
24
<input
25
type="password"
26
className="form-control"
27
id="exampleInputPassword1"
28
placeholder="Password"
29
/>
30
</div>
31
<div className="form-check mb-4">
32
<input type="checkbox" className="form-check-input" id="exampleCheck1" />
33
<label className="form-check-label" for="exampleCheck1">
34
Accept term and conditions
35
</label>
36
</div>
37
38
<button type="submit" className="btn btn-primary">
39
Submit
40
</button>
41
</form>
42
</div>
43
</div>
44
</div>
45
)
46
}
47
48
export default App

เมื่อเข้า http://localhost:3000 จะได้หน้าตาแบบนี้

React Form Login

เก็บ State แต่ละ Field

ทีนี้ การที่เราจะ handle ค่าของ Input แต่ละตัว เราก็ต้องทำการสร้าง state เพื่อมาเก็บ ยิ่งหน้า Form เรามี Field เยอะเท่าไหร่ เราก็ต้องเก็บ State มากขึ้น เท่านั้น ตอนนี้ใช้วิธีเก็บแยกก่อน ตอนนี้เรามีแค่ email, password และ toc (Term & Condition) ก็เลยได้แบบนี้

1
function App() {
2
const [email, setEmail] = useState('');
3
const [password, setPassword] = useState('');
4
const [term, setTerm] = useState(false):
5
6
return ();
7
}

จากนั้น แต่ละ Input เราก็แค่ handle ด้วย onChange คือทุกๆครั้ง ที่ input มีการเปลี่ยนแปลงค่า เราก็ setState() ให้มันซะ แบบนี้

1
<input
2
type="email"
3
className="form-control"
4
id="exampleInputEmail1"
5
aria-describedby="emailHelp"
6
onChange={(e) => setEmail(e.target.value)}
7
placeholder="Enter email"
8
/>

ของ Password และ Term ก็เช่นเดียวกัน เพียงแต่ Term เป็น checkbox ทำให้เราใช้ e.target.checked แทน แบบนี้

1
<input
2
type="checkbox"
3
className="form-check-input"
4
id="exampleCheck1"
5
onChange={(e) => setTerm(e.target.checked)}
6
/>

ต่อมา เราก็ทำการ handleSumbit ตรง form ด้วย onSubmit ซะ โดยการสร้าง function ขึ้นมา ตัวนึง แบบนี้

1
const onSubmit = (e) => {
2
e.preventDefault()
3
4
const payload = {
5
email,
6
password,
7
term
8
}
9
10
console.log('submit value', payload)
11
}
12
13
;<form onSubmit={onSubmit}>...</form>

ลองเปิดเว็บ http://localhost:3000 ทีนี้เวลากรอกข้อมูล แล้วกด Submit เราก็จะได้ค่าของเราแล้ว ก็แค่เอาค่า นี้ POST ไปที่ Server อาจจะเป็น Native Fetch api หรือ axios ก็ได้ เช่น

1
const onSubmit = async (e) => {
2
const payload = {...}
3
4
const response = await fetch('/api/auth/login', {
5
method: 'POST',
6
headers: {
7
'Content-Type': 'application/json'
8
},
9
body: JSON.stringify(payload)
10
}).then(res => res.json())
11
}

เพียงแค่นี้เราก็จัดการกับ Form ได้แล้ว

React Form Login

Handle หลายๆ Inputs

สุดท้าย ถ้าเกิดว่าเรามี Input มากขึ้น เราต้องมานั่ง setState() มานั่งกำหนด onChange เปลี่ยนค่านิดหน่อย ก็รู้สึกลำบาก เราสามาถเก็บ state เดียวกันได้ โดยใช้เป็น Object แทน แบบนี้

1
function App() {
2
const [input, setInput] = useState({
3
email: '',
4
password: '',
5
term: false
6
});
7
8
const handleChange = e => {
9
const { target } = e;
10
const { name } = target;
11
const value = name === 'term' ? target.checked : target.value;
12
13
setInput({
14
...input,
15
[name]: value
16
});
17
}
18
19
return ();
20
}

จะเห็นว่าเราเก็บ ตัวแปรเป็น State เดียวแบบ Object และสร้าง handleChange เอาไว้เป็น Handler ของ onChange จากนั้น ก็ทำการ setInput() ค่าโดยใช้ Computed Property Name ของ ES6 เพื่อ set ค่า key value ให้ตรงกับ e.target.name (ต้องตั้งชื่อ input) และ Destructuring object เพื่อใช้ค่า input เก่า อัพเดทค่าเฉพาะ input ที่ onChange เท่านั้น

แต่จะเห็นว่า มีการเช็คด้วยว่า name เท่ากับ term จะใช้ e.target.checked นั่นเอง แต่ input ปกติจะใช้ e.target.value

จากนั้น input ทั้งหลาย ก็เหลือแค่นี้

1
<input
2
type="email"
3
className="form-control"
4
id="exampleInputEmail1"
5
aria-describedby="emailHelp"
6
onChange={handleChange}
7
placeholder="Enter email"
8
name="email"
9
/>

เป็นอันเรียบร้อย เราก็ยังได้ค่าเหมือนเดิม สิ่งที่ง่ายคือ ไม่ต้องทำหลายๆ State เราก็แค่เก็บ state เป็น form หน้านั้นๆไปเลย ทีนี้จะมี Fields เพิ่ม เราก็ไม่ต้องเพิ่ม state เราเพิ่ม key ใน object ได้เลย

สุดท้าย Code ทั้งหมดของ App.js ก็ได้แบบนี้ หากใครติดปัญหา หรือไม่ตรง ก็ลองเปรียบเทียบดูได้ครับ

1
import React, { useState } from 'react'
2
import './App.css'
3
4
function App() {
5
// const [email, setEmail] = useState('');
6
// const [password, setPassword] = useState('');
7
// const [term, setTerm] = useState(false);
8
9
const [input, setInput] = useState({
10
email: '',
11
password: '',
12
term: false
13
})
14
15
const handleChange = (e) => {
16
const { target } = e
17
const { name } = target
18
const value = name === 'term' ? target.checked : target.value
19
20
setInput({
21
...input,
22
[name]: value
23
})
24
}
25
26
const onSubmit = (e) => {
27
e.preventDefault()
28
29
console.log('submit value', input)
30
}
31
32
return (
33
<div className="container">
34
<div className="row mt-4">
35
<div className="col-12 col-md-6 offset-md-3">
36
<h2 className="my-4 text-center">LOGIN</h2>
37
38
<form onSubmit={onSubmit}>
39
<div className="form-group">
40
<label for="exampleInputEmail1">Email address</label>
41
<input
42
type="email"
43
className="form-control"
44
id="exampleInputEmail1"
45
aria-describedby="emailHelp"
46
onChange={handleChange}
47
placeholder="Enter email"
48
name="email"
49
/>
50
</div>
51
<div className="form-group">
52
<label for="exampleInputPassword1">Password</label>
53
<input
54
type="password"
55
className="form-control"
56
id="exampleInputPassword1"
57
placeholder="Password"
58
name="password"
59
onChange={handleChange}
60
/>
61
</div>
62
<div className="form-check mb-4">
63
<input
64
type="checkbox"
65
className="form-check-input"
66
id="exampleCheck1"
67
name="term"
68
onChange={handleChange}
69
/>
70
<label className="form-check-label" for="exampleCheck1">
71
Accept term and conditions
72
</label>
73
</div>
74
75
<button type="submit" className="btn btn-primary">
76
Submit
77
</button>
78
</form>
79
</div>
80
</div>
81
</div>
82
)
83
}
84
85
export default App

สวัสดี

Happy Coding

Authors
avatar

Chai Phonbopit

เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust

Related Posts