สวัสดีครับวันนี้เราจะมาดูเรื่องของ Props และ State ซึ่งเป็นเรื่องที่ค่อนข้างสําคัญ และใช้งานบ่อยใน React ผมจะอธิบาย และสอนการใช้งานไปที่ละตัวนะครับ ดังนี้
Props
Props (Properties) ให้ลองนึกถึง HTML เจ้า Props ก็คือ Attributes ของ HTML นั่นเอง เช่น href, src หรือ class
<a href="#" class="link">Click me!</a>
<img src="/path/to/picture.png" />
และ Props มีประโยชน์อย่างไร? มันมีประโยชน์ตรงที่ใช้ส่งผ่านข้อมูลระหว่าง Component หนึ่ง ไปยังอีก Component หนึ่ง ตัวอย่าง ในตัวอย่างนี้ผมจะใช้ Project เดิมที่สร้างขึ้นจากบทความที่แล้ว เรื่อง เริ่มต้น React ด้วย Create React App โดยเราจะลองสร้าง Component hello โดยจะแสดงผลข้อมูลที่รับมา ผ่าน Props ซึ่งเราจะส่งข้อมูลให้ Component hello แบบนี้
<Hello message="This is message sent from App" />
และที่ไฟล์ hello.js เราก็ต้องนําข้อมูลมาแสดงผล สามารถเขียน Code ได้ดังนี้
import React from 'react'
class Hello extends React.Component {
render() {
return (
<div>
<h1>Hello my name is Thiti</h1>
<h1>{this.props.message}</h1>
</div>
)
}
}
export default Hello
จะเห็นว่าเราสามารถเข้าถึงข้อมูลได้จาก this.props ข้อสังเกตุอีกอย่างคือ ใน render(){…} จะต้อง return jsx element เดียวเท่านั้น ผมจึงใช้
render() {
return (
<h1>Hello my name is Thiti</h1>
<h1>{this.props.message}</h1>
)
}
แต่ถ้าเราไม่ต้องการใช้
render() {
return (
<React.Fragment>
<h1>Hello my name is Thiti</h1>
<h1>{this.props.message}</h1>
</React.Fragment>
)
}
ผลลัพธ์จะได้ประมาณนี้ครับ
ในกรอบสีแดงคือข้อมูลที่ถูกส่งเข้ามาผ่าน Props
State
State เป็นข้อมูลที่ถูกเก็บ และใช้งานภายใน Component ซึ่งทุกกครั้งที่ข้อมูลใน State ถูก Set ค่าใหม่ React จะทําการ Render Conponent ใหม่ ทําให้ UI มีการเปลี่ยนแปลงตามค่าที่ถูกเปลี่ยนเสมอ วิธีการใช้งาน State เริ่มต้นด้วยการ Set ค่า Default ให้กับ State ด้วยคําสั่ง this.state = {} สามารถเข้าถึงข้อมูลได้ด้วยคําสั่ง this.state และสามารถ Set หรือแก้ไขข้อมูลได้ด้วยคําสั่ง this.setState() ดูตัวอย่างด้านล่างครับ
import React from 'react'
class Hello extends React.Component {
constructor(props) {
super(props)
this.state = {
counter: 0
}
}
handleClick() {
this.setState({ counter: this.state.counter + 1 })
}
render() {
return (
<div>
<h1>Hello my name is Thiti</h1>
<h1>{this.props.message}</h1>
<button onClick={this.handleClick.bind(this)}>Imcrement counter</button>
<h1>counter: {this.state.counter}</h1>
</div>
)
}
}
export default Hello
จากตัวอย่างด้านบนผมได้เพิ่มการใช้งาน State เข้าไปในไฟล์ hello.js โดยสร้างปุ่มขึ้นมาหนึ่งปุ่ม เมื่อกดจะไปเปลี่ยนค่า counter โดยบวกเพิ่มเข้าไปทีละ 1 ผมจะแบ่ง Code ออกเป็นสามส่วนดังนี้ครับ
ผมจะอธิบายไปทีละส่วนนะครับ **ส่วนที่ 1 : **เป็นส่วนที่ผม Set ค่า Default ให้กับ counter ใน State ซึ่งผมให้ค่าเริ่มต้นเป็น 0 ส่วนที่ 2 : handleClick() เป็น function ที่ผมสร้างขึ้นมาสําหรับ เปลี่ยนค่าของ counter ใน State ซึ่งวิธีการ เปลี่ยนค่าใน State ทําได้โดยใช้คําสั่ง this.setState() แบบนี้ครับ
this.setState({
key: value
})
ในตัวอย่าง ผมนําค่า counter เดิมมาบวก 1 แล้ว set ให้กับ counter ใน State จึงเขียน code ได้ดังนี้
this.setState({ counter: this.state.counter + 1 })
ส่วนที่ 3 : เป็นส่วนสําหรับแสดงผล ซึ่งผมเอาค่า counter ใน State มาแสดงผล โดยใช้ this.state.counter แบบนี้ครับ
<h1>counter: {this.state.counter}</h1>
และ ผมก็สร้างปุ่มขึ้นมาเพื่อกดเพิ่มค่าของ counter โดยกําหนด Event onClick ของปุ่มให้ไปเรียก Function handleClick() เพื่อเพิ่มค่า counter ใน State ซึ่งการทํางานผมอธิบายไปในส่วนที่สอง จะเขียน Code ได้ดังนี้
<button onClick={this.handleClick.bind(this)}>Increment counter</button>
การส่ง Function ไปให้ onClick จะต้อง .bind(this) ด้วย เนื่องจาก handleClick() ที่ส่งเข้าไป จะถูก Execut โดย Tag button ดังนั้น เมื่อเราเรียกใช้ this ใน handleClick() จะเป็นการอ้างถึง Object ของ Tag button เราจึงต้องใช้ .bind(this) เพื่อบอกว่า เมื่อใดที่เรียก this ใน handleClick() จะหมายถึง Object ของ React แทน เพิ่มเติม การ Set State โดยการนําข้อมูลเก่ามาเปลี่ยนแปลง อาจจะทําให้เกิดปัญหาได้ ทาง React จึงแนะนําให้ Set state แบบ Function แทน ซึ่ง Function ก็มี 1 argument เป็น state ก่อนหน้า และ return เป็น new state ดังตัวอย่างนี้
this.setState(function(prevState) {
return {
counter: prevState.counter + 1
}
})
สามารถเขียนเป็นแบบ ES6 เทห์ๆ ได้แบบนี้
this.setState(prevState => ({
counter: prevState.counter + 1
}))
จะได้หน้าตาประมาณนี้ เมื่อกดปุ่ม counter จะเพิ่มขึ้นทีละ1
สรุป
เราจะใช้ Props เมื่อต้องการส่งข้อมูลกันระหว่าง Conponent ซึ่งข้อมูล อาจจะเป็นข้อมูลทั่วไป หรือเป็น Function ก็ได้ เราจะใช้ State เมื่อต้องการเก็บข้อมูล และเมื่อใดข้อมูลนั้นเปลี่ยนแปลงแล้วให้ UI เปลี่ยนด้วย