ไม่มีชื่อบทความ
ถ้าเราใช้ Next.js แล้วแยกเนื้อหาเป็นไฟล์ JSON (เช่นสำหรับรองรับหลายภาษา หรือเพื่อความเป็นระบบ), แล้วในประโยค ๆ หนึ่งมีบางคำที่ต้องใส่ลูกเล่น (เช่น เน้นสี, เอียง, หรือทำให้เป็นลิงก์), วิธีที่นิยมทำกันคือ ใช้การทำ mark หรือ tag ในเนื้อหา JSON แล้วแปลงกลับเป็น JSX ตอน render
วิธีทำ: ใส่ markup ลงใน JSON แล้ว parse ที่ component
1. ตัวอย่าง JSON
{
"greeting": "สวัสดี <strong>คุณผู้ใช้</strong> ยินดีต้อนรับ"
}
หรือถ้าอยากซับซ้อนขึ้น:
{
"greeting": [
"สวัสดี ",
{ "type": "strong", "text": "คุณผู้ใช้" },
" ยินดีต้อนรับ"
]
}
2. Render แบบแปลง HTML string เป็น JSX
ถ้าใช้แบบแรก (<strong>...</strong>) เราสามารถใช้ dangerouslySetInnerHTML ได้:
export default function Greeting({ content }) {
return (
<div dangerouslySetInnerHTML={{ __html: content.greeting }} />
)
}
ข้อควรระวัง: ต้องมั่นใจว่า content ปลอดภัย (sanitize แล้ว) เพื่อป้องกัน XSS
3. Render แบบ object (ปลอดภัยกว่า)
ถ้าใช้แบบ array + object (แบบที่สอง), เขียนตัว parser ได้แบบนี้:
function renderRichText(richTextArray) {
return richTextArray.map((item, index) => {
if (typeof item === 'string') return item;
if (item.type === 'strong') return <strong key={index}>{item.text}</strong>;
if (item.type === 'em') return <em key={index}>{item.text}</em>;
if (item.type === 'link') return <a key={index} href={item.href}>{item.text}</a>;
return item.text;
});
}
แล้วใช้แบบนี้:
export default function Greeting({ content }) {
return (
<div>
{renderRichText(content.greeting)}
</div>
)
}
4. ถ้าใช้ i18n library อย่าง i18next
จะมีฟีเจอร์ที่ชื่อว่า Trans component ที่ช่วยให้เราทำสิ่งนี้ได้อย่างสะดวกโดยใช้ <0>, <1> แบบนี้ในข้อความ เช่น:
{
"greeting": "สวัสดี <strong>{{name}}</strong> ยินดีต้อนรับ"
}
ถ้าบอกลักษณะของ "ลูกเล่น" ที่อยากทำเพิ่มเติม (เช่น ใส่ hover, ทำ tooltip, ทำ animation ฯลฯ) เราสามารถวางโครง JSON และ renderer ให้ได้ละเอียดขึ้นอีกนะ.