https://flexboxfroggy.com/#th
Sunday, August 27, 2023
Monday, July 24, 2023
Hello/สวัสดี i18n สร้างเว็บรองรับหลายภาษาบน React
สวัสดีครับผมแมกซ์นะครับ อากาศเย็นซะงั้นหรือผมรู้สึกไปเอง เหมือนจะไม่สบาย วันนี้มานำเสนอเครื่องมือช่วยในการสร้างและจัดการภาษาภายในเว็บ ซึ่งเป็นสิ่งสำคัญอย่างหนึ่ง ในตอนแรกผมสร้างเว็บแอพ โดยทั้งหมดใช้ภาษาอังกฤษ และมาลองคิดทบทวน ถามผู้ใช้อีกที สิ่งที่เค้าต้องการคือภาษาไทยสิ !เข้าใจง่าย ตรงไปตรงมา เราทำให้ผู้ใช้คือคนไทย งั้นก็เปลี่ยนทำเป็นไทยเลยไหม แต่สิ่งที่อยากได้ด้วยคือความสากล จึงเป็นที่มาของการใช้แนวคิด i18n เว็บรองรับหลายภาษา
i18n ??? หลายคนอาจจะผ่านตามาบ้าง i18n เนี่ยมันมาจาก Internationalization ยังไงหน่ะหรอก็เริ่มด้วย i จบด้วย n ตรงกลางมี 18 ตัวอักษรเลยกลายเป็น i18n ยังมี l10n มาจาก Localization หรือ k8s มาจาก Kubernetes แบบนี้ก็ได้หรอ !
เอา Console ลองนับ เออหว่ะ 555+ เพื่อ เดี๋ยวมือคนไปลองนับจะเหนื่อยเปล่า
react-i18next คือ internationalization addon ที่ใช้งานได้กับ React โดยในการเขียนโค้ดจะต่างจากเดิมนิดเดียวตัวอย่าง
<div>Just simple content</div>
หลังจากใช้ react-i18next โค้ดจะเป็นลักษณะนี้
<div>{t('simpleContent')}</div>
คือเปลี่ยนจากใช้ค่าตรงๆ เป็นการเรียกฟังก์ชั่นแล้วโยนพารามิเตอร์เป็น Key ของคำนั่นไปแทน เพื่อแสดงผลตามภาษาที่เราเลือกขณะนั้น ซึ่งสิ่งที่เราต้องเตรียมการดังนี้
เริ่มด้วยติดตั้ง react-i18next ไปที่โปรเจคของเพื่อนๆก่อน
# npm
$ npm install react-i18next --save
ไฟล์ที่ต้องสร้างเพิ่มเติม หรือ แก้ไข
my-app
├── locales
│ ├── en
│ └── translations.json
│ ├── th
│ └── translations.json
└── src
└── i18n.js
└── index.js
- ไฟล์ translations.json ใน locales
{
"title": "Welcome to react using react-i18next",
"description": {
"part1": "This is part 1.",
"part2": "This is part 2."
}
}
ไฟล์ json ที่เก็บ key และ value ไว้ทั้งสองไฟล์ภาษามี key เหมือนกัน ต่างที่ value
{
"title": "ยินดีต้อนรับเข้าสู่การใช้ react-i18next บน react ",
"description": {
"part1": "นี่คือส่วนที่ 1",
"part2": "นี่คือส่วนที่ 2"
}
}
- ไฟล์ i18n.js ใน src ตัว instance ไว้กำหนดตั้งค่า
import i18n from 'i18next';
import Backend from 'i18next-xhr-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { reactI18nextModule } from 'react-i18next';i18n
.use(Backend)
.use(LanguageDetector)
.use(reactI18nextModule)
.init({
fallbackLng: 'en', // have a common namespace used around the full app
ns: ['translations'],
defaultNS: 'translations', debug: true, interpolation: {
escapeValue: false, // not needed for react!!
}, react: {
wait: true
}
});
export default i18n;
- ไฟล์ index.js ใน src
import './i18n';
เพิ่ม import instance เมื่อสักครู่เข้าไปด้วยเพียงเท่านั้น
- ไฟล์ Component ของเราทุกไฟล์ถ้าต้องการให้รองรับการแสดงผลหลายภาษาต้องทำดังนี้
Import ตัว translate ไว้ใช้ในการ Export class นี้
import { translate } from "react-i18next";
เปลี่ยนการ Export ตัวเก่าเป็นผ่านตัว translate
// short for only loading one namespace:export default translate("translations")(Login);
ใน render()
ทำการแกะของจาก props และสร้างตัวแปรฟังก์ชั่นสลับภาษาไว้ใช้
render() {
const { t, i18n } = this.props;
const switchingLanguage = () => {
if (i18n.language === "en") {
i18n.changeLanguage("th");
} else {
i18n.changeLanguage("en");
}
};return(
<div>
//...
</div>
);
}
เมื่อทุกอย่างพร้อมแล้ว Component นี้ก็จะสามารถรองรับหลายภาษาได้แล้วโดยเรียก t ฟังก์ชั่นโยน key เป็น title เข้าไป
<div> {t('title')} </div>
การสลับภาษาสามารถเรียกใช้ switchingLanguage()
ที่เราสร้างไว้ได้เลย ตัวอย่างมี ตัวหนังสือ EN/TH ไว้เมื่อกดภาษาก็จะสลับภาษาไปมา
<a onClick={() => switchingLanguage("en")}>{t("label.enth")}</a>
ก็จะได้ของหน้าตาแบบนี้ เว็บสองภาษาคลูๆไป
จบอ่าา หวังเพื่อนๆจะอย่าง งง 55 ถ้าอ่านและทำตามเอาเป็นว่าได้เป็นไอเดีย ให้คนที่แวะเข้ามาดูว่ามันทำได้แบบนี้ละกันนะครับ ไม่ได้ลงรายละเอียดเพราะมันมีเยอะกว่านี้อีกนะเออ ทำได้มากกว่านี้ บั๊บบายไปหล่ะครับ ก่อนจากมีลิ้งให้ไปต่อถ้าสนใจ
Source : https://medium.com/@themaxaboy/hello-%E0%B8%AA%E0%B8%A7%E0%B8%B1%E0%B8%AA%E0%B8%94%E0%B8%B5-i18n-%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87%E0%B9%80%E0%B8%A7%E0%B9%87%E0%B8%9A%E0%B8%A3%E0%B8%AD%E0%B8%87%E0%B8%A3%E0%B8%B1%E0%B8%9A%E0%B8%AB%E0%B8%A5%E0%B8%B2%E0%B8%A2%E0%B8%A0%E0%B8%B2%E0%B8%A9%E0%B8%B2%E0%B8%9A%E0%B8%99-react-a491cfb7fc16
Tuesday, July 18, 2023
มาทำความรู้จัก React Context API กันเถอะ
เมื่อโปรเจคของเราใหญ่มากขึ้นเรื่อยๆ เรามักจะเจอกับปัญหาการจัดการState วันนี้ผมจะมาพาทุกคนไปรู้จักกับReact APIตัวหนึ่งที่ช่วยให้เราสามารถจัดการStateได้สะดวกมากยิ่งขึ้น โดยเฉพาะในโปรเจคขนาดใหญ่
What is Context?
ContextคือReact APIที่ช่วยให้เราสามารถแชร์ข้อมูลระหว่างComponentsได้โดยไม่ต้องส่งProps
เมื่อก่อนสมัยที่เรายังไม่มีContextหากเราต้องการแชร์ข้อมูลกันระหว่างComponentsเราต้องประกาศStateไว้ที่Top-Level Componentและส่งเป็นPropsลงมาท่ีChildren Componentsเพื่อให้แต่ละComponentสามารถใช้ข้อมูลร่วมกันได้
Why?
สมมติว่าจุดแต่ละจุดในแผนภาพด้านบนเป็นตัวแทนของComponentต่างๆ และให้ComponentsสีดำแทนComponentsที่มีการใช้ข้อมูลร่วมกัน ในทางตรงกันข้ามComponentsสีขาวจะไม่มีการใช้ข้อมูลร่วมกันเลย
เนื่องจากLeft ComponentและGrand-child of Right Componentต้องการใช้ข้อมูลร่วมกัน เราจึงต้องประกาศStateที่จะแชร์ข้อมูลไว้ที่Top-Level Componentและส่งเป็นPropsไปให้Left ComponentและGrand-child of Right Componentแต่เนื่องจากComponentนี้ไม่ได้อยู่ติดกับTop-Level Componentมันจึงจำเป็นต้องส่งPropsไปให้Right ComponentและChild of Right Componentก่อน แล้วจึงส่งต่อให้Grand-child of Right Component
คำถามคือทำไมComponentsที่ไม่ได้ใช้ข้อมูลร่วมกับLeft ComponentและGrand-child of Right componentต้องมาทำหน้าที่ส่งต่อPropsให้ด้วย วิธีนี้ทำให้โค้ดของเราดูไม่สบายตาเท่าไหร่นัก และนอกจากนี้หากPropsที่ส่งมามีการเปลี่ยนแปลง Componentsที่ทำหน้าที่ส่งข้อมูลให้ก็จะต้องRe-renderตามไปด้วย โดยที่ไม่จำเป็นเลย
การRe-renderนั้นควรเกิดขึ้นในComponentที่ใช้ข้อมูลนั้นๆเท่านั้น ไม่เช่นนั้นในที่สุดแล้วอาจทำให้เกิดปัญหาด้าน Performance ได้
และนี่จึงเป็นคำตอบของคำถามที่ว่าเรามีContextไว้ทำไม Contextเกิดขึ้นมาเพื่อลบข้อเสียที่ได้กล่าวมาข้างต้น
Contextช่วยให้เราสามารถใช้ข้อมูลร่วมกันระหว่างComponentsได้ โดยที่ไม่ต้องใช้Propsหากเราต้องการใช้ข้อมูลที่ใด ก็เรียกใช้Contextที่Componentนั้นพอ Componentsอื่นๆ และหากข้อมูลภายในContextเปลี่ยนแปลง ก็จะเกิดการRe-renderเฉพาะComponentsที่ใช้Contextนั้นเท่านั้น
นอกจากนี้ Context ยังช่วยทำให้ComponentsของเราสามารถReuseได้ง่ายขึ้นอีกด้วย เนื่องจากมันไม่ได้ผูกกับPropsแล้ว
When?
Context นั้นควรใช้ในกรณีที่จำเป็น เนื่องจากเป็นการเพิ่มความซับซ้อนให้แก่โค้ดของเรา ทำให้เราเจอความลำบากมากขึ้นเมื่อต้องมาแก้ไขโค้ดในภายหลัง
จากDOM Treeด้านบนจะเห็นได้ว่าComponent1,6,7,8ต่างต้องการใช้งานข้อมูลร่วมกัน และแต่ละComponentนั้นอยู่ในระดับที่แตกต่างกันทั้งแนวตั้งและแนวดิ่ง การส่งเป็นPropsลงมาจะทำให้ทุกComponentต้องถือPropsเดียวกัน ทั้งที่บางComponentอาจไม่จำเป็นต้องใช้เลย ดังนั้นจึงควรใช้Contextเพื่อหลีกเลี่ยงปัญหาดังกล่าว
ตัวอย่างกรณีที่ไม่จำเป็นต้องใช้Context เช่นเรามี3Componentsที่ต้องใช้ข้อมูลร่วมกัน แต่ว่าแต่ละComponentอยู่ห่างกันไม่เกิน1Level เคสแบบนี้การประกาศStateที่Component 1และส่งPropsมาที่Component2,4อาจเหมาะสมกว่า เนื่องจากจะเห็นได้ว่าไม่มีComponentไหนที่ได้รับข้อมูลโดยที่ไม่จำเป็นเลย
How?
เมื่อเรารู้จักContextและรู้ว่าควรใช้งานมันเมื่อไหร่แล้ว ก็ถึงเวลาเรียนรู้ว่าจะใช้งานมันได้อย่างไร
ก่อนที่ผมจะแนะนำวิธีการใช้งานContext ต้องขออนุญาตแนะนำContext APIที่จำเป็นต้องรู้จักกันก่อน
React.createContext
APIตัวแรกที่ต้องรู้จักคือcreateContext มันเป็นตัวสร้างContext Objectขึ้นมาเพื่อเก็บข้อมูลที่ต้องการใช้ร่วมกัน, ใช้เป็นProvider, และใช้Subscribe Contextที่Componentsปลายทาง
Context.Provider
อย่างที่เรียนให้ทราบด้านบน การสร้างContext Objectจะมาพร้อมกับProvider ซึ่งเจ้าProviderจะช่วยให้Componentsปลายทางทั้งหลายสามารถSubscribeการเปลี่ยนแปลงข้อมูลภายในContextได้
Class.contextType
ใช้เพื่อSubscribeข้อมูลภายในContextที่Componentsปลายทาง แต่จะใช้ได้กับClass Componentเท่านั้น และหากSubscribe Contextด้วยวิธีนี้เพียงวิธีเดียวจะทำให้เราสามารถSubscribeได้เพียงหนึ่งContextเท่านั้น
Context.Consumer
ใช้เพื่อSubscribeข้อมูลภายในContextที่Componentปลายทาง โดยที่สามารถใช้ได้กับทั้งClassและFunctional Component การSubscribe Contextด้วยวิธีนี้จะทำให้เราสามารถSubscribeได้มากกว่าหนึ่งContext
React.useContext
ใช้เพื่อSubscribeข้อมูลภายในContextที่Componentปลายทาง ใช้ได้กับFunctional Componentเท่านั้น การSubscribe Contextด้วยวิธีนี้จะทำให้เราสามารถSubscribeได้มากกว่าหนึ่งContext
วิธีนี้เป็นวิธีที่ง่ายและนิยมที่สุดในการSubscribeข้อมูลจากContext
Example
เรารู้จักContextกันมามากพอแล้ว สิ่งต่อไปที่เราอยากเห็นคงหนีไม่พ้นตัวอย่างการใช้งาน
ต้องขอบอกว่าวิธีการใช้งานที่ผมกำลังจะนำเสนอเป็นหนึ่งในวิธีการใช้งานเท่านั้นและไม่การันตีว่าจะเป็นวิธีการที่ดีที่สุด
ในที่นี้เราจะสร้างCart Contextเพื่อใช้เก็บข้อมูลสินค้าในรถเข็น
เริ่มแรกเราต้องสร้างContext Objectขึ้นมาก่อน แล้วจึงสร้างCartProvider Componentเพื่อใช้เป็นที่เก็บStateและActionต่างๆของContext
ในCartProviderเราจะสร้างStateขึ้นมาเพื่อใช้เป็นที่เก็บข้อมูลต่างๆที่ต้องการใช้ร่วมกัน และสร้างAction Fucntionต่างๆที่เราจะอนุญาตให้Componentปลายทางสามารถทำได้เช่น addToCart
ต่อมาเราจะสร้างตัวแปรcartStoreขึ้นมาเพื่อเป็นValueให้แก่PropของProvider ซึ่งPropตัวนี้จะเป็นค่าที่เราจะส่งไปให้Consumerนั่นเอง
ซึ่งค่าของตัวแปรcartStoreผมดีไซน์แยกออกเป็นสองส่วนคือส่วนของStateและAction จากโค้ดจะเห็นได้ว่าStateจะอยู่ในLevelของroot ส่วนActionจะถูกwrapไว้ด้วยkey cartAction อีกที
วิธีนี้ทำให้เมื่อเราอ่านโค้ดที่Componentปลายทาง เราสามารถเข้าใจได้ในทันทีเลยว่ามันกำลังใช้ค่าจากStateหรือกำลังจะทำActionอะไรบางอย่างกับContextอยู่
สุดท้ายเราจะสร้างCustom Hookชื่อว่าuseCartContextขึ้นมา ประโยชน์ของHookตัวนี้คือทำให้เราไม่ต้องImport useContextและCartContextในทุกComponentปลายทาง ที่ต้องการSubscribe เพียงImport useCartContextไปตัวเดียวก็สามารถใช้ข้อมูลของContextได้แล้ว ทำให้โค้ดคลีนขึ้น
เมื่อสร้างCartProviderเสร็จแล้ว เราก็จะนำProvider ตัวนี้ไปครอบเป็นParent Component ที่ระดับApp levelเพื่อให้ทุกComponentในแอปของเราสามารถเรียกใช้งานContextตัวนี้ได้นั่นเอง
หากเรามีมากกว่าหนึ่งContextเราก็สามารถสร้างProviderอื่นๆขึ้นมาได้และนำมาใช้ในรูปแบบเดียวกัน
หากComponentไหนต้องการใช้งานCartContextเพียงแค่Import useCartContextมาใช้ ก็จะสามารถใช้งานได้โดยที่ข้อมูลที่ได้รับจะเป็นข้อมูลที่แชร์กันระหว่างComponents
หากเราต้องการSubscribe Context Valueที่Class Componentเราอาจสร้างHigh Order Componentขึ้นมาตัวหนึ่งเพื่อใช้ส่งContext Valueไปเป็นPropให้กับComponentปลายทาง
Caution!!!
จุดที่ทุกคนควรรู้และระวังคือContextไม่มีการพิจารณาว่าComponentsปลายทางสมควรที่จะถูกRe-renderหรือไม่ เพราะฉะนั้นทุกครั้งที่ข้อมูลภายในContextเปลี่ยนแปลง Componentปลายทางจะถูกสั่งRe-renderด้วย
หากเราต้องการให้โค้ดบางส่วนทำงานก็ต่อเมื่อข้อมูลในContextบางตัวเปลี่ยนเท่านั้น ไม่ใช่ทุกตัว เราอาจใช้useMemoเข้ามาช่วยได้ครับ
หากสนใจศึกษาข้อมูลเกี่ยวกับContext APIเพิ่มเติม สามารถดูได้จากOfficial Documentเลยครับ
Source : https://medium.com/@pakpoom.thawee/%E0%B8%A1%E0%B8%B2%E0%B8%97%E0%B8%B3%E0%B8%84%E0%B8%A7%E0%B8%B2%E0%B8%A1%E0%B8%A3%E0%B8%B9%E0%B9%89%E0%B8%88%E0%B8%B1%E0%B8%81-react-context-api-%E0%B8%81%E0%B8%B1%E0%B8%99%E0%B9%80%E0%B8%96%E0%B8%AD%E0%B8%B0-511d1bd332f1