หยุดความวุ่นวายของ Redux Store มาใช้ GraphQL ด้วย Apollo React!

Yuttana Kungwon
Jitta Engineering
3 min readDec 20, 2016

--

เดิมทีการพัฒนา mobile app ด้วย React Native นั้น สิ่งที่วุ่นวายที่สุดคงหนีไม่พ้นการจัดการ state ต่างๆ และเพราะมันเป็น react เลยจึงต้องมองเป็น component ไปเกือบซะทั้งหมด แต่พอแอพใหญ่ขึ้น มี component มากขึ้น state ก็มากขึ้น data-flow ของเราจะเริ่มวุ่นวายละ…
Redux นั้นมาช่วยเราจัดการเรื่องนี้แทน พูดสั้นๆคือมาช่วยจัดการเรื่องของ state และ action ต่างๆที่จะเกิดขึ้นให้มีระเบียบเรียบร้อยมากขึ้น

…ทีนี้ปรกติแล้วเนี่ย redux นั้นจะประกอบไปด้วยสามส่วนหลักๆคือ
1. Action
2. Reducer
3. Store

จะบอกทำไมวะเนี่ย…

เรื่องของมันก็คือ ถ้าเราต้องการ fetch data จาก server บน restful ปรกติ ถ้าเราใช้ redux จัดการ state ของแอพ มันจะเกิดเหตุการณ์ประมาณนี้
1. user เปิดแอพหน้านึง สมมุติว่าหน้าแสดง feed ข่าวอะไรซักอย่าง
2. action ไปจัดการเรื่องของตัวเองและ return `TY​PE` และ `DATA`ออกมา
3. reducer เจอ type ของตัวเอง ก็จะทำการสร้าง state ใหม่ของตัวเองขึ้นมา และแก้ไข หรือ จัดการข้อมูลที่ต้องการส่งไปเก็บบนโกดัง (Store)
4. component เห็นการเปลี่ยนแปลงเพราะของใน state เปลี่ยน ก็เลย re-render ให้ใหม่ ของก็อัพเดทใหม่บน UI

จบเรื่อง redux !

ประเด็นคือ กว่าจะทำอะไรแต่ละที ต้องไปสร้าง action, reducer เก็บของลง store จะใช้ตอนไหนก็มา dispatch… หลายขั้นตอนเหมือนกัน

GraphQL มิติใหม่ของวงการ API Query!

GraphQL คือ query language อย่างหนึ่งที่ถูกพัฒนาขึ้นมาโดย Facebook ซึ่งโดยตัวมันเองเนี่ย จะ define backend api ด้วยลักษณะที่เป็น schema ทั้งหมด ตรงนี้รายละเอียดเชิงลึกจะไม่ขอพูดถึงนะครับ เพราะทำไม่เป็น แนะนำให้ลองไปอ่านดูที่ tutorial นี้ก่อนให้เข้าใจเรื่องเบสิค เช่น query, mutation

พูดกันง่ายๆคือ ถ้าจะใช้ GraphQL Server เราก็ควรจะมี Client Framework ไว้ติดต่อกับมันด้วย และ Facebook ก็ทำออกมาตัวนึง ชื่อว่า Relay แต่ผมมองว่ามันค่อนข้างซับซ้อนมากเกินไป เลยแนะนำ Apollo Client เพราะใช้ง่ายกว่ามากๆ

ประเด็นมันอยู่ที่ว่า หากเราใช้ Apollo client หรือ relay แล้วเนี่ย เราสามารถลืมความวุ่นวายของ Redux ไปได้เลย คือ query เสร็จ แสดงผล ก็จบ ถ้า data เปลี่ยน แล้วพี่เค้า re-render ให้เอง เพราะ apollo หรือ relay เอง framework พวกนี้มักจะบอกว่าตัวเองมี store อยู่แล้ว เวลาเราเอาไปใช้ไม่ต้องสร้าง action, reducer ใดๆทั้งสิ้น!

Apollo / Relay จะทำงานร่วมกับ Smart Component เสมอ

หลังจากเริ่มรู้จัก graphql basic แล้ว ให้ลืมเรื่องของ RestFul API แบบเก่าทิ้งไปก่อน แล้วมาดูกันว่ามันง่ายกว่ายังไงในฝั่งของ client!

ก่อนอื่น clone project นี้มาเปิดดูก่อน https://github.com/Thunderbird7/React-Native-GraphQL-Apollo-Client

จะเห็นว่ามีโค้ดอยู่ไม่กี่หน้า เพราะเป็นตัวอย่างอยาก query ของโง่ๆจาก GraphQL Server มาดูกัน

ขั้นแรก… ลอง npm install และ run react-native run-ios
เพื่อ build app ขึ้นมาดูก่อน จะเป็นว่ามีลิสแสดงรายการหลังเรื่องต่างๆ (ถ้า error แก้เองนะครับ)

ถ้ากด row แต่ละอันจะพบกับรายละเอียดของหนังเรื่องนั้น เป็น modal กากๆแบบนี้

ได้แบบนี้แสดงว่าแอพทำงานปรกติ ทีนี้ลองจิตนาการดูก่อนนะครับ ถ้าเราใช้ redux ไป fetch ของจาก API มาแสดงผลแบบนี้จะเกิดอะไรบ้าง และมีอะไรบ้าง…
หลายไฟล์เลยใช่มั้ยครับที่ต้องสร้าง action, reducer ไหนจะมา mapStateToprops… ไหนจะมากำหนด constant type blah blah

คราวนี้ลองเปิดไฟล์ index.ios.js ดูสิว่าวุ่นวายมั้ย

จะเห็นว่า คล้ายๆ redux นะครับ pattern ของมัน เช่น provider นี่เหมือนกันเลย ถ้า component ไหนไม่ได้อยู่ใน provider ของมัน ก็จะไม่นู้จัก store แต่ของ apollo นั้นเราเพียงสร้าง client instance ขึ้นมา ตรงนี้จะใช้ networkInterface เพื่อติดต่อกับ graphql server กันก่อน (ดู option อื่นๆ http://dev.apollodata.com/core/apollo-client-api.html#constructor)

จากนั้น connect apollo client ไปที่ component ทั้งหมด ด้วย apolloProvider ง่ายๆก็คือ component ใดๆที่ต้องการ access graphql data ต้องอยู่ใน provider นี้ (เหมือนอยู่ใน redux store อะครับ)

จากนั้นลองเปิด App.js ดู จะเห็นวิธีการ Connecting & query data ดูดีๆ ไม่มี action, reducer อะไรนะ ไม่มี mapStateToProps ด้วย

หลักๆคือดูแค่คำสั่ง query ใน gqlอันนี้เราสามารถใส่คำสั่ง query ของ graphql ได้เลยตามใจ ผ่าน lib ชื่อ graphql-tag ตัวนี้เป็นแค่ template literals ช่วยในการเขียน query ให้มันเหมือนๆเวลาเราเอาไปเทสใน graphigl (graphql interface)

อ้อ…! ลืมบอกไป เมื่อเรามี graphql server เราสามารถเข้าไปทดสอบ query, mutaion ที่เราต้องการได้เลยมี UI ให้ใช้ เช่นโปรเจคนี้ผมใช้ demo server ที่นี่ http://graphql-swapi.parseapp.com

หลังจากนั้นก็ยัด query เข้าไปที่ component ผ่านgraphql libอีกที แค่นี้ smart component หน้านี้ก็จะ connect กับ graphql แล้วครับ ง่ายมาก ไม่วุ่นวาย แต่ถ้าลึกกว่านี้เช่นเรื่องของ mutation ก็จะยาวกว่านี้นิดนึง

ทีนี้วิธีใช้… ง่ายมาก การที่เรายัด query เข้าไปใน component ตัว apollo เองจะแอบ mapToprops ให้เราเอง นั่นหมายความว่าเราสามารถใช้ props ใดๆ ใน this.props ได้เลย ทีนี้พอของเปลี่ยน state เปลี่ยน ก็ render ใหม่ เหมือน redux เปี๊ยปปป แต่ความเนี๊ยบ เท่กว่าเยอะ

จบ!

--

--