Auth project

เนื้อหาในตอนนี้เราจะเริ่มด้วยการสร้าง project ใหม่ขึ้นมาชื่อว่า auth ดังนั้น ให้เราเปิด terminal แล้วเข้าไปที่ folder ที่ใช้สำหรับสร้างโปรเจ็กท์ในเครื่องของคุณผู้อ่าน จากนั้น run คำสั่งต่อไปนี้

ติดตั้ง ESLint

เนื่องจากหากเราต้องการใช้ ESLint เราจะต้องทำการติดตั้งให้กับโปรเจ็กท์นั้นๆ โดยให้เปิด terminal แล้วรันคำสั่งต่อไปนี้ใน root project

จากนั้นสร้างไฟล์ชื่อว่า .eslintrc ไว้ที่ root project แล้วใส่ข้อมูลดังต่อไปนี้

Mockup

หน้าตาของโปรเจ็กท์ auth เป็นไปตามรูปดังต่อไปนี้

authmockup

คือจะมีอยู่เพียงแค่สองหน้าจอ ซึ่งสามารถเอามาแตก component ได้ดังนี้

authmockupdetail

จะเห็นว่า ทั้ง Header, Card และ CardSection ที่เราเคยสร้างเอาไว้ใน Project ก่อนหน้านี้ สามารถเอา reuse ใน project นี้ได้ต่อ

โดยหน้าจอนี้จะทำหน้าที่ให้ user สามารถ log in เข้าระบบโดยใช้ Firebase Authentication ซึ่งเป็นระบบที่พัฒนาโดย Google ที่ใช้ email และ password เป็นข้อมูลขาเข้า

Project architecture

สถาปัตยกรรมของโปรเจ็กท์นี้ค่อนข้างเรียบง่าย ดังภาพต่อไปนี้

architecture

เราสามารถพัฒนาได้ทั้ง ios และ android โดยใช้ code แบบเดียวกัน (แต่ต้องวางทั้งในไฟล์ index.ios.js และ index.android.js)

เราจะสร้าง Root component ให้มีชื่อว่า App โดยภายในจะมีการเรียกใช้ LoginForm component อีกทีหนึ่ง

สร้าง App component

ก่อนอื่นให้เราสร้าง folder src\ ขึ้นมา แล้วภายใน folder นั้นให้สร้างไฟล์ App.js ขึ้นมา

ภายใน App.js ให้เพิ่ม code ไปด้งนี้

จากนั้น ให้แก้ code ภายในทั้ง index.android.js และ index.ios.js ให้เป็นไปตามนี้

ให้ทำการ refresh emulator เราจะเห็นหน้าจอมี text คำว่า ‘An App!’ ปรากฎขึ้นมา (ในกรณีที่คุณยังไม่ได้เปิด emulator ให้รันคำสั่ง react-native run-ios หรือ react-native run-android ตรงตำแหน่ง root project)

Reuse components

ในขั้นนี้เราจะทำการนำ component จากโปรเจ็กท์ albums มาใช้งานในโปรเจ็กท์นี้

ให้เราทำการสร้าง folder components\ ภายใต้ src\ และภายใต้ src/components/ ให้สร้าง folder common อีกที จากนั้น ให้ copy ไฟล์ดังต่อไปนี้มาไว้ที่ src/components/common/

  • album/src/components/Button.js
  • album/src/components/Card.js
  • album/src/components/CardSection.js
  • album/src/components/header.js

ดังนั้น ตอนนี้โครงสร้าง folder ของ auth project จะเป็นดังนี้

คราวนี้เราจะอำนวนความสะดวกให้นักพัฒนาในการ import component เหล่านี้ไปใช้ใน component อื่นๆ โดยวิธีการจะเป็นไปดังแผนภาพต่อไปนี้

screen-shot-2559-11-26-at-11-14-38-am

หากภายใน folder ใดก็ตาม เราได้สร้าง index.js ไว้ เราจะสามารถ import component ทั้งหมดภายใน folder นั้นโดย import เพียงแค่ชื่อ folder เท่านั้น ซึ่งจะช่วยประหยัดจำนวน code ที่เราต้องเขียนลงไปได้หลายบรรทัดทีเดียว

เริ่มต้นโดยให้สร้างไฟล์ index.js ภายใน src/components/common ซึ่งจะทำให้โครงสร้าง folder ของระบบเราเป็นดังนี้

โดยภายใน index.js นี้จะมี code ดังนี้

คราวนี้ประเด็นสำคัญก็คือ การจะทำ index.js เพื่อ export component รวมแบบนี้ ภายในไฟล์ของ component แต่ละตัวจะไม่สามารถ export ด้วย default ได้อีกต่อไป จำเป็นจะต้อง export แบบ named export โดยให้ปรับ code ในขั้นตอนการ export ของแต่ละ component ดังนี้

จากนั้นให้นำ component เหล่านี้มาใช้งาน โดยให้เปิดไฟล์ auth/src/App.js แล้วแก้ code ดังนี้

จะเห็นได้ว่า การ import component นั้น เราสามารถ import แบบ named import โดยเรียกระบุแค่ระดับ folder เท่านั้น

หากไม่มีอะไรผิดพลาด เมื่อเรา refresh แล้วหน้าจอจะเป็นดังนี้

screen-shot-2559-11-26-at-1-36-40-pm

Firebase Project Creation

สำหรับโปรเจ็กท์นี้ เราจะใช้ firebase authenticate เพื่อช่วยให้การทำงานง่ายยิ่งขึ้น โดยในขณะที่ผมกำลังเขียนอยู่นี้ Firebase ได้เตรียมบริการไว้แล้วกว่า 15 บริการ

ก่อนอื่นให้ทำการติดตั้ง Firebase module ใน project ก่อน โดยให้เปิด terminal แล้วเข้าไปที่ root project แล้วพิมพ์คำสั่งต่อไปนี้

จากนั้นเราสร้างโปรเจ็กท์ใน Firebase ขึ้นมาก่อน โดยเข้าไปที่

https://console.firebase.google.com

screen-shot-2559-11-26-at-1-43-33-pm

หมายเหตุ: การใช้งาน Firebase คุณจำเป็นต้องมี account ของ google ก่อน หากยังไม่มีให้ไป register เพื่อสร้าง account ใหม่ มิฉะนั้น จะใช้บริการของ Firebase ไม่ได้

ให้คลิกปุ่ม “สร้างโครงการใหม่” จากนั้นให้ตั้งชื่อ โครงการเป็น ‘auth’ และเลือกประเทศให้เป็น ‘ไทย’ ดังรูปscreen-shot-2559-11-26-at-1-44-35-pm

ระบบจะพาให้เราเข้ามาที่หน้า dashboard ของโปรเจ็กท์นี้ screen-shot-2559-11-26-at-1-46-07-pm

ทางเมนูด้านซ้ายให้เลือก Authenticate เพื่อ setup บริการนี้screen-shot-2559-11-26-at-1-46-20-pm

ให้คลิกปุ่ม “ตั้งค่าวิธีการลงชื่อเข้าใช้”

จากนั้นคลิกเลือก อีเมล/รหัสผ่าน เพื่อเปิดใช้งานscreen-shot-2559-11-26-at-1-47-16-pm

คลิกเปิดใช้ และบันทึก

screen-shot-2559-11-26-at-1-47-36-pm

Firebase client setup

ให้กลับไปที่หน้า home ของโปรเจ็กท์ โดยให้คลิก auth ที่เมนูด้านซ้าย

auth

จากนั้นให้คลิกที่ “เพิ่ม Firebase ไปยังเว็บแอพของคุณ”

fbconfig

จากนั้นให้ทำการ copy code ทั้งหมดที่ปรากฎขึ้นมาในหน้า popup เพื่อเตรียมนำไปใช้

screen-shot-2559-11-26-at-2-26-26-pm

จากนั้นให้เปิดไฟล์ auth/src/App.js แล้วนำ firebase เข้ามาใช้ในระบบดังนี้

จุดที่ต้องปรับก็คือ config ให้ประกาศเป็น const (จาก code ใน google จะเป็น var) แล้วพวก value ทุกตัวใน config ต้องครอบด้วย ‘ (single quote) ไม่ใช่ ” (double quote)

ส่วนการ import firebase นั้น ให้เขียนอยู่เหนือบรรทัดนี้

เพราะการ import จากพวก module มาตรฐานที่เราติดตั้งมาจาก npm ไม่ควรจะวางไว้ด้านล่างการ import custom module เพราะ javascript จะตีความ module มาตรฐานเหล่านี้ ว่าเป็น custom module

สร้างหน้า LoginForm

ให้สร้างไฟล์ src/components/LoginForm.js ทำให้ตอนนี้เรามีโครงสร้าง file ดังนี้

แล้วเพิ่ม code เข้าไปดังนี้

จากนั้นให้ทำการ import LoginForm เข้าไปใน App component ดังนี้

จากนั้นก็ให้ลอง refresh emulator

screen-shot-2559-11-26-at-2-58-44-pm

About TextInput

คราวนี้เราจะมาเติม TextInput เข้าไปในหน้า LoginForm เพื่อรองรับการกรอก email และ password โดยให้ปรับ code ภายใน LoginForm.js ดังนี้

TextInput เป็น component ที่ประหลาดนิดนึงตรงที่ว่า หากเราไม่บอก height กับ width ให้กับมัน มันจะไม่แสดงตัวบนหน้าจอ ดังนั้นเราต้องระบุขนาดของมันทุกครั้ง หากเรา refresh emulator เราจะเห็นหน้า screen เป็นดังนี้

screen-shot-2559-11-27-at-7-30-37-am

จะเห็นว่า TextInput ตัวที่สองจะไม่ปรากฎบนหน้าจอเพราะเราไม่ได้ระบุขนาดให้กับมัน

จาก code ข้างต้น นอกเหนือไป style แล้ว เรายังมีการแทรก state เข้าไปใน component ด้วย โดย code ที่เราสามารถ refactor ให้มันดูดขึ้นได้ ก็คือ code บรรทัดนี้

หากยังจำเรื่องกันได้ ใน ES6 นั้น เมื่อใดที่มีการ assign variable ให้กับ key ที่มีชื่อเดียวกัน สามารถตัดทอนจากการเขียนในรูปแบบ { text: text } มาเป็น { text } ได้ ดังนั้น ให้เปิดไฟล์ LoginForm.js แล้วแก้ code ดังนี้

จาก code ข้างต้น เราสามารถสรุปขั้นตอนการทำงานของ TextInput ใน component ตัวนี้ได้ดังแผนภาพต่อไปนี้

textinputstep

โดยสรุปก็คือ เมื่อใดที่ user พิมพ์อักษรตัวใดก็ตามลงไปใน TextInput ตัว event ที่ชื่อว่า onChangeText จะถูกเรียกใช้งาน ซึ่งภายใน event นั้น เราจะทำการ setState เพื่อเปลี่ยนค่า state ที่ชื่อว่า text ให้มีค่าเท่ากับ text ภายใน TextInput

ทุกครั้งที่มีการ setState ตัว component จะถูก render ใหม่ และเวลา render component ทุกครั้ง ตัว component จะไม่รู้เลยว่า จะต้องใช้ value จากที่ใด ดังนั้น เราจะต้องกำหนดค่าให้มันผ่าน attribute ที่มีชื่อว่า value ซึ่งในที่นี้ เรากำหนดให้มันมีค่าเท่ากับ this.state.text

Create reusable Input component

เนื่องจากใน LoginForm เราต้องการ text input ที่มี label อยู่ทางด้านซ้ายของตัว input ด้วย ดังนั้นคงจะเป็นการดีกว่า หากเราสร้าง custom component ขึ้นมาเพื่อใช้สำหรับ login form

ให้เราสร้างไฟล์ชื่อว่า src/component/common/Input.js ขึ้นมา โดยตอนนี้โครงสร้างไฟล์ภายใน folder ของโปรเจ็กท์นี้จะเป็นดังนี้

จากนั้นให้เติม code เข้าไปดังนี้

จุดที่อยากเน้นในจังหวะนี้ก็คือ attribute ภายใน style ที่ชื่อว่า flex

ในตัวอย่างก่อนหน้านี้ เวลาเราใช้ flex จะเป็นไปเพื่อให้ตัว component นั้นกินพื้นที่ด้านกว้างจากซ้ายไปขวาเต็มพื้นที่ โดยกำหนดค่าให้เท่ากับ 1

หากในแนวใดที่มี component เพียงแค่ตัวเดียว การกำหนดค่า flex: 1 จะหมายถึงให้ component นั้นยึดพื้นที่ตามแนวนั้น 100% แต่สำหรับการบรรจุ component หลายๆ ตัวลงไปใน container เดียวกัน การระบุค่า flex ที่แตกต่างจะส่งผลต่อการจัดสัดส่วนการวาง component นั้นๆ ภายใน container ดังกล่าว

จาก code ข้างต้น เราใช้ <View> เป็น container และตัวของมันไม่ได้มี component ข้างเคียงมาแย่งพื้นที่ ดังนั้น การกำหนดให้ flex: 1 จึงหมายถึงการขยายความกว้างของ <View> ให้เต็มพื้นที่

แต่สำหรับ <Text> และ <TextInput> นั้น มันคือการนำสอง component ไปวางไว้ภายใต้ container เดียวกัน ดังนั้น การกำหนดค่า flex จะมีผลต่อการจัดสัดส่วนของทั้งสอง component

กล่าวคือ ค่า flex ของ <Text> มีค่าเท่ากับ 1 และค่า flex ของ <TextInput> มีค่าเท่ากับ 2 นั่นแปลว่า มีการแบ่งสัดส่วนภายใน <View> ออกเป็น 3 ส่วน (1 + 2) แล้ว <Text> เอาไป 1 ส่วน <TextInput> เอากรรมสิทธิ์ไป 2 ดังรูป

flex

หลังจากนั้นให้เปิดไฟล์ src/components/common/index.js ขึ้นมา แล้วปรับ code ดังนี้

จากนั้นเปิดไฟล์ src/components/LoginForm.js ขึ้นมา แล้วแก้ code ดังนี้

อย่าลืมลบ <TextInput /> จาก <CardSection> ตัวที่สองออกไปด้วย เพราะตอนนี้เราตัด TextInput ออกจาก component ตัวนี้แล้ว

ปรับแต่ง Input

หากเราลอง refresh emulator แล้วลองพิมพ์คำบางคำลงไปในช่อง Email แล้วจะเห็นว่า ทาง TextInput จะใส่ feature autocorrect เข้ามาให้อัตโนมัติ ซึ่งเป็นฟีเจอร์ที่หลายคน (รวมทั้งตัวผมรำคาญ) ดังรูป

screen-shot-2559-11-27-at-12-09-14-pm

ดังนั้น เราจะมาทำการปิดฟีเจอร์นี้ทิ้งไป ด้วยการระบุไปใน <TextInput> ดังนี้

นอกจากนั้น เราจะปรับให้ TextInput ของเราแสดง placeholder text วิธีการก็ง่ายๆ นั่นคือ ใส่ attribute placeholder เข้าไปดังนี้

และสุดท้าย สำหรับฟิลด์ password จะต้องปรับให้ input แสดง text เป็น wildcard เพื่อป้องกันไม่ให้บุคคลที่สามเห็น password จากหน้าจอ วิธีการก็ให้เราใส่ attribute secureTextEntry เข้าไป ดังนี้

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

จากนั้นให้ปรับ code ภายใน src/components/LoginForm.js ดังนี้

ภายใน LoginForm component เราได้ปรับค่าภายใน state ให้มีชื่อสอดคล้องกับจุดประสงค์การใช้งานของมันมากกว่าเดิม (จากเดิมเป็นแค่ text เท่านั้น)

ให้ลอง refresh ดู หากไม่มีอะไรผิดพลาด จะได้เห็นหน้าตาของ app ดังนี้

screen-shot-2559-11-27-at-12-34-02-pm

ในส่วนของ warning ในเรื่อง onPress function ภายใน Button เป็นเพราะ เรายังไม่ได้ระบุค่า onPress function ให้กับ Button เลย มันจึง warning ออกมาอย่างที่เห็น ซึ่งเราจะมาแก้กันในเนื้อหาในตอนหน้า

สรุป

เราได้สร้าง Project ใหม่ขึ้นมาชื่อ auth สำหรับศึกษาเรื่องการ authenticate ผ่าน Firebase ซึ่งเป็นบริการ backend จาก google โดยเนื้อหาในตอนนี้เป็นการเตรียม UI screen ของโปรเจ็กท์นี้ในหน้า login ในตอนหน้า เราจะมาลุยกันในเรื่องของการ authenticate ผ่าน Firebase ของจริงกัน

1 COMMENT