Firebase Database

Firebase JSON schema

Firebase database จะเก็บข้อมูลในรูปแบบของ JSON ซึ่งมันก็คือ javascript object นั่นแหละ ไม่ได้มีอะไรซับซ้อน

คราวนี้มาดูหน้าตาของ database ของ schema ของระบบภายใน manager กันดูบ้าง

screen-shot-2559-12-10-at-6-00-20-am

หนึ่ง user จะมีความสัมพันธ์กับ employee แบบ 1-to-many หรือ 1 user มี employee ในสังกัดหลายคน โดยหากเอามาเขียนเป็น JSON จะได้หน้าตาประมาณนี้

screen-shot-2559-12-10-at-6-01-55-am

จริงๆ แล้ว firebase ไม่แนะนำให้ทำ nested data แบบเดียวกับที่เพิ่งแสดงให้เห็นกันไป แต่เพื่อความเรียบง่ายของ tutorial ในขั้นนี้ เราจะใช้การออกแบบในทำนองนี้ไปก่อน

Firebase data security

ก่อนอื่นเราต้องมากำหนด security กันก่อนสำหรับ firebase database เพื่อป้องกันการ access มั่วๆ จาก user ที่ไม่ถึงประสงค์

วิธีการก็คือ ให้เราไปที่ https://console.firebase.google.com แล้วเข้าไปที่โปรเจ็กท์ manager ของเรา จากนั้นคลิก Database ที่เมนูด้านซ้ายมือ จากนั้นเลือก tab กฎ (หรือ rules ในกรณีเป็นภาษาอังกฤษ) จากนั้นให้ลบ rule ตัวเดิมทิ้งไป แล้วให้ใช้ rule ต่อไปนี้แทน

ความหมายก็คือ rule นี้จะ apply เฉพาะกับ users schema เท่านั้น โดยจะเปิดสิทธิ์ในการ read and write ให้กับ user ที่มี uid ตรงกับ ข้อมูลใน row ที่มี uid เดียวกับ user

จากนั้นก็กดปุ่ม เผยแพร่ (หรือ publish หากเป็นภาษาอังกฤษ) ดังรูป

screen-shot-2559-12-10-at-6-18-17-am

สร้าง employee create action

คราวนี้เราจะ assign action creator ให้กับปุ่ม create ภายในหน้า employeeCreate กัน ก็เหมือนเดิมครับ เริ่มต้นเราต้องเริ่มจาก type constant ก่อน

1. สร้าง type constant

ให้เปิดไฟล์ types.js ขึ้นมา แล้วเพิ่ม code ดังนี้

2. สร้าง action creator

ให้เปิดไฟล์ EmployeeActions.js ขึ้นมา แล้วเพิ่ม action creator ใหม่เข้าไปดังนี้

ไม่มีอะไรมาก เราแค่จะลอง log ดูว่า เวลาเรากดปุ่ม create แล้วมันรับข้อมูลจากหน้าจอมาอย่างไร ก่อนจะตัดสินใจ implement อะไรลงไปใน action creator ตัวนี้

จากนั้นให้ลองเอา action creator ตัวนี้ไปลองใช้ใน EmployeeCreate.js ดูก่อน โดยให้เปิดไฟล์ ดังกล่าวขึ้นมาแล้วแก้ code ดังนี้

จากนั้นให้เราลองเปิด emulator พร้อม เปิด debugger แล้วให้เข้าไปถึงหน้า employeeCreate แล้วลองกรอกข้อมูล แต่ไม่ต้องไปกรอก shift ปล่อยให้มันเป็น Monday อยู่อย่างนั้น จากนั้นกดปุ่ม create เราจะได้หน้า console ประมาณนี้

screen-shot-2559-12-10-at-6-32-58-am

จะเห็นว่า ข้อมูลจะวิ่งมาแค่ name กับ phone แต่ shift ไม่วิ่งเข้ามา นั่นเป็นเพราะ ตอนนี้หากเราไม่คลิกเลือก shift จาก picker บนหน้าจอ ระบบมันจะมอง shift ไม่มี value

วิธีแก้ปัญหาก็คือ เซตค่า default ให้กับ shift ซึ่งเรามี 3 ทางเลือก

  1. ให้ไปแก้ที่ค่า INITIAL_STATE ภายใน manager/src/reducers/EmployeeFormReducer.js ให้เป็น ดังนี้

2. ตรง mapStateToProps ภายใน manager/src/components/EmployeeCreate.js เวลาที่เราจะ map ค่า state เข้าไปเป็น props ให้กับ component ตัวนี้ เราสามารถ set ค่า default props ให้กับ shift ได้หากมันมีค่าเป็น undefined

3. ภายใน manager/src/components/EmployeeCreate.js ในจังหวะที่กดปุ่ม create ในจังหวะที่มีการเรียกใช้ action creator ที่ชื่อว่า employeeCreate ให้เราตรวจสอบว่า shift มีค่าเป็น undefined หรือไม่ หากใช่ ก็ให้ใส่ค่า ‘Monday’ เข้าไป

ใครชอบแบบก็เลือกใช้วิธีนั้นไป แต่โดยส่วนตัวผมชอบวิธีที่หนึ่ง ที่ไปจัดการกับค่า default ที่ state โดยตรงภายใน reducer เพราะผมมองว่า reducer มีหน้าโดยตรงในการจัดการข้อมูลภายใน state ดังนั้น การเซตค่า default หรือค่าตั้งต้นให้กับ state/props ตัวใด ก็ดูจะเป็นการแบ่งหน้าที่การทำงานที่ดีทีเดียว (ตามความเห็นของผม)

ดังนั้น เลือกเอาเลยครับว่าจะเซตค่า default ให้กับ shift ยังไง

คราวนี้ก็ให้ลอง refresh emulator แล้วลองกรอกข้อมูล employee อีกครั้ง กดปุ่ม Create แล้วดูที่ console ว่าจะให้ผลลัพธ์เหมือนผมหรือไม่

screen-shot-2559-12-10-at-6-39-20-am

Saving data to Firebase database

เราจะนำข้อมูลจากทั้งสามฟิลด์มา save ลง Firebase database ในขั้นตอนนี้

ให้เปิดไฟล์ manager/src/actions/EmployeeAction.js ขึ้นมา แล้วเพิ่ม code ดังนี้

เนื่องจาก Firebase database มีฟอร์แมตเป็น json ดังนั้น เวลาต้องการอ้างอิงถึงชุดข้อมูลภายใน จะอ้างอิงในลักษณะแบบ path เช่น หากจะ access ข้อมูลของ user ที่มีรหัส uid = ‘l9xJXMltyqUrWXNyQhQXs5SY4Lm1‘ เราก็จะต้อง access ข้อมูลจาก

จาก code ข้างต้น จะเห็นว่า เราใช้ฟีเจอร์หนึ่งของ ES6 ที่เรียกว่า Template String ที่เราสามารถแทรก variable เข้าไปภายใน string ได้โดยตรง เพียงแค่จะต้องครอบด้วย ${ } เท่านั้น

ดังนั้น เวลาอ้างอิงถึง path ของ employees ที่เราต้องการจะ save ข้อมุลลงไปในฐานข้อมูลใน Firebase จึงสามารถอ้างโดยการเขียน code ดังนี้

โดย currentUser.uid คือ uid ของ user ที่กำลัง login อยู่ในระบบนั่นเอง

เวลาที่เราจะทำการ insert ข้อมูลเข้าไปใน Firebase Database เราจะใช้ฟังก์ชั่น push ตามด้วย object ที่ต้องการ insert ลงไป

ให้ refresh emulator แล้วกรอกข้อมูล create employee จากนั้นก็คลิกปุ่ม Create พอเสร็จแล้วก็เปิด firebase console -> Database แล้วคลิกที่ tab data เราจะเห็นภาพดังรูป

หมายเหตุ: ตอนนี้ action creator ตัวนี้ยังไม่มีการ return action ใดๆ ออกมาเลย ดังนั้น เวลาเรารัน code ตัวนี้ มันจะ error แต่ไม่เป็นไร เพราะตอนนี้เราต้องการแค่ทดสอบว่าข้อมูลมันวิ่งไป insert ใน firebase จริงหรือไม่

screen-shot-2559-12-10-at-10-30-01-am

จะเห็นได้ว่า แม้ก่อนหน้าจะไม่มีโครงสร้างข้อมูลใดๆ ไว้ใน database เลย แต่เพียงแค่เราอ้างอิง path ไว้ และ push ข้อมูลเข้ามา Firebase จะทำการสร้างโครงสร้าง database ไว้ให้

Dispatching create action

คราวนี้เราจะทำแก้ปัญหา error ที่เกิดจากการที่ employeeCreate action creator ยังไม่ได้ return action ออกไป ทำให้ Redux แสดง Error ดังที่เห็นไปก่อนหน้านี้

ดังนั้น ให้เปิดไฟล์ manager/src/actions/EmployeeAction.js ขึ้นมาแล้วแก้ code ดังนี้

เนื่องจากฟังก์ชั่น push ของ Firebase นั้นมีลักษณะเป็น promise ซึ่งก็คือฟังก์ชั่นที่มีลักษณะของ Asynchronous ดังนั้น เราจึงต้อง Redux Thunk มาเพื่อจัดการกับการ push data เข้า firebase ใน action creator ตัวนี้

ภายใน then จะมีการทำงานสองส่วน คือ ส่วนแรกจะ dispatch action ที่มี type เป็น EMPLOYEE_CREATE เพื่อส่งต่อให้ reducer ไปทำงานต่อตามธรรมเนียม Redux

ส่วนที่สองก็คือ การ routing ไปยังหน้า employeeList โดยใช้คำสั่ง Actions.employeeList สังเกตมั๊ยครับว่าการเที่ยวนี้ จะมีการใส่ argument พิเศษเข้าไปตัวนึงคือ { type: ‘reset’ } เพื่อจุดประสงค์คือ ป้องกันการใส่ปุ่ม back เข้าไปที่หน้า employeeList ซึ่งมันจะนำไปสู่หน้า login อันเป็นคนละ flow กัน

การใช้ { type: ‘reset’ } จะบอก navigator เพื่อนำ Scene มาวางทับ Scene ปัจจุบัน และ reset navigation stack ทั้งหมด หมายความว่าทำให้ scene ดังกล่าวเริ่มเป็น scene แรกของ navigation เลย (อ่านเพิ่มเติมได้ที่ https://github.com/aksonov/react-native-router-flux/blob/master/docs/API_CONFIGURATION.md#actionconst-and-scenetype-explaination)

และตามธรรมเนียมครับเมื่อสร้าง Action Creator เสร็จ ก็ต้องไปสร้าง reducer ต่อ

ให้เปิด manager/src/reducers/EmployeeFormReducer.js แล้วแก้ code ดังนี้

เมื่อไหรก็ตามที่ action มี type เป็น EMPLOYEE_CREATE reducer จะทำการ reset ค่าของ name, phone และ shift ใหม่ ซึ่งจะเป็นการเคลียร์หน้าจอ employeeCreate ไปในเวลาเดียวกัน

คราวนี้ให้ทำการ refresh emulator แล้วลองกรอกข้อมูลดู จะเห็นว่าหลังจากคลิก create ระบบจะ route ไปยังหน้า employeeList โดยทำการ add ข้อมูลเข้าไปใน Firebase พร้อมๆ กัน

Fetching data from Firebase

ตอนนี้เราจะทำการดึงข้อมูลรายการของ employee ของแต่ละ user มาแสดงในหน้า employeeList ทั้งหมด

ดังนั้น เรามาเริ่มทำ function ใหม่กันเลย โดยใช้ step เหมือนเดิม (type constant -> action creator -> reducer -> นำไปใช้จริง)

1. type constant

เปิดไฟล์ manager/src/actions/types.js แล้วเพิ่ม code ดังนี้

2. Action creator

เพิ่ม action creator โดยเปิดไฟล์ manager/src/actions/EmployeeAction.js ขึ้นมาแล้วเพิ่ม code ดังนี้

การดึงข้อมูลของ firebase จะใช้การดัก event ที่ชื่อ ‘value’ เมื่อได้มาแล้วก็ให้ทำการ dispatch action ที่แนบข้อมูลที่ดึงมาได้ไปหา reducer (payload: snapshot.val())

3. reducer

ให้สร้างไฟล์ EmployeeReducer.js ขึ้นมาภายใต้ folder manager/src/reducers/ โดยเพิ่ม code เข้าไปดังนี้

ในที่นี้เราขอดัก console.log ไว้นิดนึง เพื่อดูว่า format ข้อมูลที่ firebase ส่งมามีหน้าเป็นอย่างไร

หลังจากนั้นเพิ่ม reducer ตัวนี้ไว้ใน combineReducers โดยให้เปิดไฟล์ manager/src/reducers/index.js แล้วเพิ่ม code ดังนี้

4. นำไปใช้จริง

ให้เปิดไฟล์ employeeList.js ขึ้นมาแล้วแก้ code ดังนี้

เมื่อทำการ refresh emulator พร้อมทั้งเปิด debugger แล้ว ให้ login เข้าไปในระบบ พอถึงหน้า employeeList แล้วเราจะเห็นข้อมูลดังต่อไปนี้ใน console

screen-shot-2559-12-10-at-12-20-28-pm

จะเห็นว่า Firebase คืนค่าออกเป็น object ซึ่งภายในจะมี list ของ employee object ซ้อนอยู่ภายในอีกที ซึ่งเราจะนำมันมาแสดงในหน้า employeeList ต่อไป

Create ListView with multiple datasource

การแสดงผลภายใน EmployeeList นั้น จะต้องแสดงเป็น list ของ employee ดังนั้น component ที่เหมาะสมที่สุดสำหรับงานนี้คือ ListView ดังนั้น เราจะต้องนำ component ดังกล่าวมาใช้

ให้เปิดไฟล์ manager/src/components/EmployeeList.js ขึ้น จากนั้นให้นำ ListView มาใช้งาน โดยเขียนปรับ code ดังนี้

จะสังเกตเห็นว่า เราคราวนี้เรามีการ setup datasource ให้กับ ListView ถึงสองครั้ง โดยครั้งแรกเรา set ใน componentWillMount ซึ่งเป็นจังหวะที่เรา call employeesFetch จาก action creator ไปด้วย

อย่างที่เราก็รู้ดีว่า employeeFetch นั้นเป็นการ fetch data จาก firebase ซึ่งคาดคะเนไม่ได้ว่ามันจะ return ข้อมูลกลับมาเมื่อไหร่ ดังนั้น การ setup datasource ภายใน componentWillMount นั้น เราจะได้ props ที่ยังไม่มีค่า employees มาใช้เป็นแน่ ด้วยเหตุนี้ เราจึงต้อง setup datasource ในจังหวะที่ component จะได้รับ props ใหม่มาแน่ๆ ซึ่งเราสามารถทำได้จาก componentWillReceiveProps คือ lifecycle function ที่ทำหน้าที่ตรงนี้พอดี

componentWillReceiveProps นั้นจะถูกเรียกใช้ในจังหวะที่ component เพิ่งได้รับ props ตัวใหม่มา โดย argument ตัวแรก nextProps ก็คือ props ใหม่ล่าสุดที่ทาง component เพิ่งได้รับมาหยกๆ ดังนั้น หากเรียกใช้ nextProps จะถือเป็นการใช้ props ใหม่ล่าสุดที่เพิ่งได้รับมา จาก firebase

แปลง firebase return object ให้เป็น array

ในการ setup datasource ให้กับ ListView นั้น มี code อยู่บรรทัดนึงที่เขียนดังนี้

ตัวฟังก์ชั่น cloneWithRows นั้น จะรับ argument เป็น array แต่ตอนนี้ employees ที่เรารับตรงมาจาก Firebase นั้นเป็น object ดังนั้นเราจะต้องทำการแปลง object ตัวนี้ให้กลายเป็น array เสียก่อน

npm มี module ตัวนึงที่ช่วยเราทำงานนี้ ชื่อว่า lodash ให้เราเปิด terminal ขึ้นมา (ปิด emulator ด้วย) แล้วรันคำสั่งต่อไปนี้

จากนั้กก็ค่อยรัน emulator อีกครั้งหนึ่งเพื่อให้มัน load module ตัวใหม่นี้เข้าไปในระบบ

เราจะทำการแปลง firebase object ให้กลายเป็น array ตรง mapStateToProps โดยให้เปิดไฟล์ manager/src/components/EmployeeList.js ขึ้นมาแล้วเปิด code เข้าไปดังนี้

ในที่นี้เราจะนำค่าของ val และ uid ของ employee แต่ละตัวมาสร้างเป็น array ใหม่ โดยใช้ lodash มาแปลงให้ด้วยการใช้ฟังก์ชั่น map เข้ามาทำงานนี้

ใน render() เราได้ดัก console.log เอาไว้ เพื่อดูว่า props ที่ component ได้รับมามีหน้าตาเป็นอย่างไร

เมื่อเรา refresh emulator และเปิด debugger ไว้ พอไปถึงหน้า employeeList แล้วหน้า console จะแสดงผลดังนี้

screen-shot-2559-12-10-at-3-42-40-pm

จะเห็นว่า props ที่ชื่อ employees นั้นกลายเป็น array ที่สมาชิกแต่ละตัวคือ object ของ employee แต่ละคน

Render data with ListView

คราวนี้ก็ได้เวลานำ ListView มาใช้งานซะที

ก่อนอื่นให้สร้าง component สำหรับใช้แสดง item ใน ListView แต่ละตัว โดยให้สร้างไฟล์ ListItem.js ขึ้นมาภายใต้โฟลเดอร์ manager/src/components/ จากนั้นให้เพิ่ม code ดังนี้

คราวนี้ให้เปิดไฟล์ manager/src/components/EmployeeList.js แล้วจากนั้นปรับ code ดังนี้

จากนั้นให้เปิด emulator ลองเข้าไปที่หน้า employeeList เราจะเห็นข้อมูลดังนี้

screen-shot-2559-12-10-at-4-12-48-pm

หากเราลอง add employee ใหม่เข้ามา พอกด create ปั๊บ จะมีรายชื่อใหม่ขึ้นมาที่หน้า employeeList ทันที

Create and Edit form

สำหรับหน้าของ Employee นั้น นอกจากการ create แล้ว ยังต้องมีหน้า edit ด้วย โดยหน้าตาของทั้งสองหน้าจอจะคล้ายกันมาก ดังรูป

screen-shot-2559-12-11-at-7-19-53-am

จะเห็นว่า component ตรงส่วนกลางในส่วนของฟิลด์หลักทั้งสามฟิลด์ จะเหมือนกัน ดังนั้น เราจะ refactor โดยการดึงส่วนที่ซ้ำกันดังกล่าวไว้ใน component กลางที่สามารถนำไป reuse ได้ โดยตั้งชื่อไว้ว่าเป็น EmployeeForm ดังนั้น เราจะมี component 3 ตัวหลักคือ EmployeeCreate สำหรับ insert employee ใหม่, EmployeeForm เป็น reusable component และ EmployeeEdit สำหรับแก้ไขข้อมูลหน้าจอ

Refactoring to create reusable form

ให้สร้างไฟล์ EmployeeForm.js ขึ้นมาภายใต้ folder manager/src/components/ แล้วกรอก code (ที่ดึงมาจาก EmployeeCreate) ดังนี้

ปรับ code ใน EmployeeCreate

จากนั้นให้เปิดไฟล์ manager/src/components/EmployeeForm.js ให้ปรับ code ดังนี้

Create EmployeeEdit form

จากนั้นให้สร้างไฟล์ EmployeeEdit.js ขึ้นมาภายใต้โฟลเดอร์ manager/src/components/ แล้วเพิ่ม code ดังนี้

ปรับแก้ ListItem component

ให้เปิดไฟล์ manager/src/components/ListItem.js แล้วเพิ่ม code ในส่วนที่ทำให้ item รองรับการคลิก แล้วไปยังหน้า employeeEdit ดังนี้

จาก code ดังต่อไปนี้

หมายความว่า เราจะ route ไปยังหน้า employeeEdit โดยส่ง props ที่ชื่อ employee ไปด้วย โดยจะมีค่าเท่ากับ this.props.employee

ปรับ Router

เพิ่ม EmployeeEdit เข้าไปใน Router โดยให้เปิดไฟล์  manager/src/Router.js ขึ้นมาแล้วแก้ code ดังนี้

คราวนี้ให้ลองเปิด emulator ขึ้นมา แล้วไปที่หน้า employeeList ลองคลิกที่รายการใดรายการหนึ่งมันจะพาเราไปยังหน้า employeeEdit (หาไม่มีอะไรผิดพลาด

Save data with employeeEdit

คราวนี้เราจะมาทำให้หน้า employeeEdit สามารถ save ข้อมูลได้จริง ดังนั้น ให้เราทำการเพิ่ม action creator ขึ้นมาก่อน โดยเปิดไฟล์ manager/src/actions/EmployeeAction.js ขึ้นมาแล้วแก้ code ดังนี้

ใน employeeSave นอกเหนือไปจาก name, phone, shift ที่จะรับมาเป็น parameter แล้ว เรายังต้องรับ uid ของ employee เข้ามาด้วย เพื่อใช้ในการ query firebase สำหรับ record ที่เราต้องการจะ update

ตอนเราอ้างอิง path สำหรับ firebase นั้น คราวนี้เราจะระบุลงไปถึงระดับ employee แต่ละคน ดังนั้น รูปแบบ path จึงเป็นแบบนี้

จากนั้นก็ใช้ฟังก์ชั่น set() เพื่อ update ข้อมูลลงตรง path นั้น จากนั้นก็ log ซะหน่อยว่า saved (ยังไม่ต้องใส่ function อะไรมาก ในตอนนี้ ขอทดสอบก่อน)

จากนั้นก็ให้นำ action creator มาใช้เพื่อทดสอบจริงภายใน employeeEdit โดยให้เปิดไฟล์ manager/src/components/EmployeeEdit.js แล้วเพิ่ม code ดังนี้

ตรง componentWillMount เราใช้ฟังก์ชั่นของ lodash เพื่อไล่ดู props ของ this.props.employee ทีละ props แล้วยิ่งใส่ employeeUpdate action creator เพื่อนำข้อมูลทั้งหมดไปแสดงบน EmployeeForm หรือฟอร์กลางที่แสดงฟิลด์ name, phone และ shift

ส่วน onButtonPress เราจะใช้ employeeSave action creator ในการ update ข้อมูลภายใน Firebase โดย argument ตัวสุดท้ายหรือ uid นั้นเราจะดึงมาจาก this.props.employee ซึ่งเป็น props ที่ถูกส่งมาจาก ListItem component หากยังจำกันได้ props ตัวนี้ถูกส่งมาในจังหวะนี้

ด้วยเหตุนี้ employeeEdit จึงมี props ที่ชื่อ employee นั่นเอง

หลังจากนั้นให้ลองเปิด emulator ขึ้นมาดู แล้วของเข้าไปที่หน้า employeeEdit ของใครก็ได้ซักคนหนึ่ง จากนั้นลองเปลี่ยนข้อมูลแล้วกดปุ่ม Save Changes เมื่อเข้าไปดูที่ Firebase console ในส่วนของ database ของ employee คนนั้น ข้อมูลจะต้องเปลี่ยน และบนหน้า console จะต้องแสดงคำว่า saved!!!

Complete EmployeeEdit

คราวนี้เราจะปรับให้การ save data ของ employee ทำงานได้อย่างเต็มรูปแบบ ด้วย Redux ดังนั้นก็ตามเดิม type constant -> action creator -> reducer

1. type constant

เปิดไฟล์ manager/src/actions/types.js แล้วเพิ่ม code ดังนี้

2. action creator

เนื่องจากเราได้เพิ่ม action creator สำหรับงานนี้ไปแล้ว เพียงแต่ครั้งนี้เราจะทำให้มันสามารถทำงานได้สมบูรณ์ ให้เปิดไฟล์ manager/src/actions/EmployeeAction.js ขึ้นมาแล้วเพิ่ม code ดังนี้

action creator ทำหน้าที่สองอย่าง คือ route ไปยังหน้า employeeList แล้วทำให้มันเป็นหน้าแรกของ navigation path (ไม่มีปุ่ม back) และทำการ dispatch action data ไปยัง reducer

3. reducer

ให้เปิดไฟล์ manager/src/reducers/EmployeeFormReducer.js ขึ้นมาแล้วแก้ code ดังนี้

หลังจากที่เรา save employee เสร็จแล้วต้องทำการเคลียร์ค่าของ name, phone และ shift มิฉะนั้น state ทั้งสามตัวนี้จะติดเข้าไปอยู่ใหนหน้าอื่นๆ ของระบบด้วย เช่น หากเรากด add employee หลังจาก save employee มันจะเอาข้อมูลล่าสุดของ employee ไปใส่ในหน้า employeeCreate ซึ่งไม่ใช่สิ่งที่พึงประสงค์ (เพราะเราต้องการให้หน้า employeeCreate แสดงเป็นหน้าฟอร์มเปล่าในจังหวะที่เพิ่งเปิดเข้าไป

เปิด emulator ขึ้นมาแล้วทำการทดสอบระบบด้วยตนเองว่าทำงานได้อย่างสมบูรณ์หรือไม่

ส่ง text message ไปหา employee

ฟีเจอร์นี้จะเป็นการส่ง text message ไปทางโทรศัพท์ ให้กับผู้รับ โดยทาง npm ได้เตรียม module ไว้สำหรับการนี้ชื่อว่า react-native-communications ให้เราปิด emulator แล้วทำการติดตั้ง module ด้วยคำสั่งต่อไปนี้

จากนั้นภายใน manager/src/components/EmployeeEdit.js ให้แก้ code ดังนี้

สรุปคือ code สำหรับส่ง message นั้น ใช้ code แค่บรรทัดเดียวเท่านั้น ดังนี้

จบ คราวนี้พอเรารัน emulator แล้ว เข้าไปถึงหน้า employee เมื่อกดปุ่ม Text Schedule แล้วจะเห็นหน้าสำหรับส่ง message ในมือถือดังนี้

screen-shot-2559-12-11-at-3-21-52-pm

Modal screen

สำหรับฟีเจอร์สุดท้ายระบบนี้คือการ “ไล่พนักงานออก” หรือการลบข้อมูลพนักงานออกนั่นเอง ซึ่งแน่นอนว่า เวลาเราจะลบข้อมูลใดๆ ออกจากฐานข้อมูล จะต้องมี modal popup มาย้ำเตือนว่า แน่ใจหรือไม่ ดังนั้น ก่อนจะไปสร้าง ฟีเจอร์ fire employee ให้เราสร้าง modal component เตรียมไว้ก่อน

ให้เราสร้างไฟล์ชื่อ Confirm.js ขึ้นมาภายใต้โฟลเดอร์ manager/src/components/common/ โดยให้เพิ่ม code ไปดังนี้

สำหรับในส่วนของ Modal ที่อยู่ใน code ข้างบน คงต้องขออธิบายความหมายของ attribute แต่ละตัวซักเล็กน้อย

  1. visible เป็น boolean ซึ่งบอกว่า modal นี้จะปรากฎ หรือหายไปจากหน้าจอ
  2. transparent ทำให้ modal มีพื้นหลังโปร่งแสง
  3. animationType บอกว่า modal จะปรากฎขึ้นมาบนหน้าจอด้วย animation แบบไหน ซึ่งในที่นี้เราใช้ slide
  4. onRequestClose อันนี้เป็นtrick นิดหน่อย เพราะเมื่อไหร่ที่เราต้องใช้ modal ใน android มันจะบังคับให้เราต้องระบุ callback function ให้กับ attribute ตัวนี้ แม้จะเป็นฟังก์ชั่นว่างๆ ก็ตาม

เราสร้าง component ตัวนี้ภายใต้โฟลเดอร์ src/components/common/ เพราะหน้าจอ popup มันมีธรรมชาติเป็น component พื้นฐานที่มีการถูกนำมา reuse บ่อยครั้ง เราจึงสร้างมันไว้ภายใน common/ folder

จากนั้นให้ทำการ export ตัวมันเองออกสู่โลกภายนอก โดยเปิดไฟล์ manager/src/components/common/index.js แล้วเพิ่ม code ดังนี้

นำ Confirm มาใช้งาน

ให้เปิดไฟล์ manager/src/components/EmployeeEdit.js ขึ้นมาแล้วทำการแก้ code ดังนี้

เนื่องจากการใช้งาน popup เป็นเรื่องภายในของ component จึงไม่มีความจำเป็นที่จะไปใช้ state ของ Redux เราสามารถสร้าง และใช้งาน state ภายในตัว component ได้เลย ดังนั้น จึงสร้าง state สำหรับควบคุมการปรากฎของ popup ผ่าน state ที่ชื่อว่า showModal ซึ่งเรา set ให้มีค่า default เป็น false

เปิด emulator ขึ้นมาแล้วพอเข้าไปถึงหน้า employee แล้ว ให้ลองคลิกปุ่ม Fire Employee แล้ว จะเห็น popup ขึ้นมาดังนี้

screen-shot-2559-12-11-at-4-18-54-pm

Redux wiring

ได้เวลาใส่ฟังก์ชั่นการลบเข้าไปใน EmployeeEdit ผ่าน Redux กันแล้ว

สำหรับ ฟังก์ชั่นการลบนั้นจะไม่ได้ยุ่งเกี่ยวกับ redux’s state ดังนั้นก็ไม่จำเป็นต้องไปยุ่งกับ reducer แค่ action creator อย่างเดียวก็พอแล้ว

1. action creator

ให้เปิดไฟล์ manager/src/actions/EmployeeAction.js แล้วเพิ่ม action creator ดังนี้

เราใช้ฟังก์ชั่น remove() เพื่อลบข้อมูลออกจาก Firebase

2. นำไปใช้จริง

เปิดไฟล์ manager/src/components/EmployeeEdit.js แล้วปรับ code ดังนี้

คราวนี้พอเราเข้าไปในหน้า employee แล้วคลิกปุ่ม Fire Employee ระบบจะพาเรา route กลับมาที่หน้า employeeList แล้วรายชื่อที่เราเพิ่งลบไปจะหายไปจาก list

สำหรับผู้ที่ต้องการดู code ต้นแบบ สามารถไปดูได้ที่

https://github.com/himaeng/manager.git

สรุป

จบแล้วครับ สำหรับ  tutorial React Native & Redux หวังว่าจะได้รับความเข้าใจไปกันไม่มากก็น้อยนะครับ

พบกันใหม่ในคอร์ส Advance React