หากคุณกำลังสร้างแม้แต่เว็บแอปที่มีขนาดเล็ก คุณจะต้องจัดเก็บข้อมูลบางประเภทและส่งข้อมูลนี้ระหว่างส่วนประกอบและจากหน้าหนึ่งไปอีกหน้าหนึ่ง
โดยปกติคุณจะเก็บข้อมูลไว้ในสถานะ และคุณจัดการสถานะการแบ่งปันระหว่างเพจและส่วนประกอบโดยใช้บริบทหรือด้วย State Management Framework เช่น Redux วิธีการนี้อาจทำให้เกิดความซับซ้อนอย่างมากในแอปของคุณ และนี่คือข้อเสียเปรียบ โดยเฉพาะอย่างยิ่งหากคุณต้องการติดตามสิ่งง่ายๆ

ซูสแตนด์คืออะไร

Zustand เป็นโซลูชันที่มีน้ำหนักเบาและใช้งานง่ายในการจัดการสถานะด้วยวิธีง่ายๆ ใช้งานง่าย และจะแก้ปัญหาความต้องการส่วนใหญ่ที่คุณอาจเผชิญเมื่อพัฒนาเว็บแอปที่ต้องการการจัดการสถานะ นอกจากนี้ Zustand ยังสามารถเก็บข้อมูลระหว่างหน้าและโหลดซ้ำได้ (เพิ่มเติมในภายหลัง)



Zustand ทำงานร่วมกับ Nextjs ได้หรือไม่

ใช่! Zustand เข้ากันได้กับ Nextjs โดยสิ้นเชิง แต่ถ้าคุณต้องการคงสถานะไว้ ก็จำเป็นต้องมีการปรับแต่งบางประการ นี่เป็นเพราะวิธีการทำงานของ Nextjs แต่ด้วยการเพิ่มเติมอีกสองสามบรรทัด ทุกอย่างจะราบรื่นมาก (ในตัวอย่างของเรา เราจะคงสถานะไว้ )

เมื่อ Zustand มีประโยชน์?

ขึ้นอยู่กับกรณีการใช้งานของคุณ แต่พิจารณาว่าแม้ว่า Zustand จะเบาและใช้งานง่าย แต่ก็ทรงพลังมากและมีคุณสมบัติขั้นสูงบางอย่าง ดังนั้นทุกครั้งที่คุณเริ่มต้นใหม่ และสถานะไม่ได้ซับซ้อนมากนัก คุณสามารถลองใช้ Zustand ได้ หากคุณต้องการติดตามแบบฟอร์มหลายขั้นตอน (เช่น แบบสำรวจหรือการลงทะเบียนที่ซับซ้อน) หากคุณต้องการจัดเก็บรายละเอียดผู้ใช้บางส่วน หากคุณต้องการติดตามรถเข็น (เช่นในตัวอย่างที่เราจะแสดง ). นอกจากนี้ Zustand ยังอนุญาตให้คงข้อมูลเหล่านี้ไว้โดยใช้ localStorage (หรือวิธีการจัดเก็บข้อมูลไคลเอ็นต์อื่นๆ) เพื่อให้ผู้ใช้ไม่สูญเสียสิ่งต่างๆ ในการโหลดซ้ำหรือในเซสชันอื่นๆ

Zustand ทำงานอย่างไร?

ในระดับพื้นฐานที่สุดในการทำงานกับ Zustand คุณจะสร้าง Store ซึ่งเป็น hook แบบกำหนดเองเพื่อให้สามารถนำไปใช้ได้ทุกที่ในแอปของคุณ:

import create from 'zustand'
const useStore = create(set => ({
  bears: 0,
  increasePopulation: () => set(state => ({ bears: state.bears + 1 })),
}))

ในเพจหรือส่วนประกอบ คุณเพียงแค่เข้าถึง hook เพื่อให้คุณสามารถเข้าถึงสถานะและฟังก์ชันต่างๆ ได้ ทุกครั้งที่สถานะได้รับการอัปเดต ส่วนประกอบจะถูกเรนเดอร์อีกครั้ง:

function Home() {
  const bears = useStore(state => state.bears)
  const increasePopulation = useStore(state => state.increasePopulation)
   return {
      <h1>{bears}</h1>
      <button onClick={increasePopulation}>Add Bear</button>
   }
}

เรากำลังสร้างอะไร?

ในตัวอย่างนี้ เราจะใช้ประโยชน์จาก Zustand เพื่อติดตามรถเข็นของผู้ใช้ในเว็บไซต์อีคอมเมิร์ซสมมติ
โดยละเอียด:

  • เราจะเก็บรถเข็นทั้งหมดไว้ในสถานะ: จำนวนสินค้าในรถเข็น, จำนวนสินค้าในรถเข็น, รายการสินค้าในรถเข็น
  • เราจะสร้างฟังก์ชันสถานะบางอย่าง: เพิ่มสินค้าลงในรถเข็น, อัปเดตจำนวนสินค้าในรถเข็น, ลบสินค้าออกจากรถเข็น และทำความสะอาดรถเข็น
  • เราจะจัดเก็บรถเข็นไว้ใน localStorage เพื่อให้ผู้ใช้ไม่สูญเสียรถเข็นเมื่อเรียกดูหน้าเว็บไซต์ของเราและแม้ว่าจะออกจากไซต์และกลับมาใหม่ในภายหลัง
  • เราจะใช้โค้ดที่จำเป็นในหน้าเว็บของเราเพื่อให้สถานะคงอยู่กับ Nextjs

การจัดทำโครงการ

หากคุณต้องการติดตามโดยไม่ต้องเขียนโค้ด คุณสามารถดาวน์โหลดพื้นที่เก็บข้อมูลสำหรับโปรเจ็กต์นี้ได้ที่นี่:



เริ่มต้นโครงการด้วย:

npx create-next-app state-mgt

จากนั้นเข้าสู่โฟลเดอร์ที่สร้างขึ้นใหม่ state-mgt และติดตั้งโมดูล Zustand:

npm install zustand

นอกจากนี้เรายังจะใช้ Tailwind CSS เพื่อจัดรูปแบบไซต์ของเรา ซึ่งเป็นทางเลือกโดยสิ้นเชิง โดยปฏิบัติตามเอกสารอย่างเป็นทางการ



จากนั้นเราทำความสะอาดโปรเจ็กต์โดยเริ่มจากไฟล์ index.js ที่เกือบจะว่างเปล่า

การกำหนดค่าร้านค้า

สิ่งแรกที่เรากำหนดร้านค้าของเราใน store/store.js

โดยทั่วไปแล้วจะกำหนด hook ของเรา (useCart) ที่เริ่มต้นโดยใช้วิธี create ร้านค้า (ซึ่งขยายเป็น persistone) จะมี สถานะประกอบด้วย total(ตัวเลขที่แสดงถึงมูลค่ารวมของรถเข็น), totalqty(ตัวเลขที่มีสินค้าทั้งหมดในรถเข็น), cartContent (อาร์เรย์ที่มีสินค้าในรถเข็น โดยจะมีรายละเอียดสินค้า เช่น จำนวน รหัส ชื่อ และอื่นๆ)
ต่อไป เราจะกำหนดฟังก์ชันที่จะอัปเดต (set ) รัฐ:

  • addTocartจะเพิ่มผลิตภัณฑ์ลงใน cartContent และเพิ่ม total และ totalqty
  • updatecartเหมือนกับครั้งก่อน แต่แทนที่จะเพิ่มบรรทัดใหม่ลงใน cartContent ให้อัปเดตจำนวนบรรทัดที่มีอยู่แทน
  • clearCartรีเซ็ตสถานะเป็นค่าเริ่มต้น (ว่าง)
  • removeFromCartลบบรรทัดออกจากเนื้อหารถเข็นและอัปเดต ผลรวมและ totalqty

ชื่อที่ระบุที่ส่วนท้ายของไฟล์คือชื่อของออบเจ็กต์ใน localStorage ที่นี่คุณยังสามารถระบุวิธีการจัดเก็บข้อมูลของการคงอยู่ ("ข้อมูลเพิ่มเติมเกี่ยวกับเอกสารอย่างเป็นทางการ")

ผลิตภัณฑ์

เพื่อให้สิ่งต่าง ๆ เรียบง่ายและหลีกเลี่ยงการตั้งค่าฐานข้อมูล เราจึงเก็บผลิตภัณฑ์ของเราเป็นออบเจ็กต์ในไฟล์ lib/products.js

ผลิตภัณฑ์ทุกชิ้นเป็นออบเจ็กต์ที่มีรหัส ชื่อ ราคา และรายละเอียดรูปภาพ (รูปภาพจะถูกจัดเก็บไว้ในโฟลเดอร์ Nextjs public) เพิ่มผลิตภัณฑ์ได้มากเท่าที่คุณต้องการ/ชอบ

หัวข้อ

ในตัวอย่างนี้ เราจะใช้ส่วนหัวทั่วไปเพื่อสาธิตการใช้ state ในส่วนประกอบและการคงอยู่ของสถานะในหน้าต่างๆ:

ส่วนหัวจะแสดงมูลค่าของรถเข็นและจำนวนสินค้าในรถเข็นเสมอ ดังที่ได้กล่าวไว้ก่อนหน้านี้ เนื่องจากเรากำลังทำงานใน Nextjs วิธีการเรนเดอร์เพจ (SSR และ SSG) ไม่อนุญาตให้เข้าถึงสถานะถาวรบนไคลเอนต์โดยตรง วิธีแก้ไขชั่วคราวคือการเข้าถึงเมื่อคอมโพเนนต์ถูกเมาท์แล้ว ในกรณีนี้ เราไม่ได้เข้าถึงและแสดงผล total และ totalqtyที่มาจาก useCarthook แต่เรากำลังแสดงผล mytotal และ mytotalqtyซึ่งเป็นรัฐท้องถิ่นสองรัฐที่ตั้งค่าเป็นสถานะ Zustand เมื่อมีการเปลี่ยนแปลง โดยพื้นฐานแล้ว นี่เป็นเพราะความจริงที่ว่าเพจถูกเรนเดอร์บนเซิร์ฟเวอร์ และในระหว่างกระบวนการเรนเดอร์นี้ พวกเขาไม่สามารถเข้าถึงที่เก็บข้อมูลไคลเอนต์เพื่ออ่านค่าได้ เมื่อเพจถูกไฮเดรทแล้ว พื้นที่เก็บข้อมูลไคลเอ็นต์จะถูกเข้าถึงและดึงค่าออกมา ณ จุดนี้ค่าไคลเอนต์ขัดแย้งกับค่าเซิร์ฟเวอร์ส่งผลให้เกิดคำเตือน การมี "การเรนเดอร์สองครั้ง" นี้จะช่วยแก้ปัญหาได้

อีกวิธีในการแก้ปัญหานี้ใน Nextjs คือการจัดเก็บสถานะจากระยะไกลด้วย (เช่นบน Redis) เพื่อให้เซิร์ฟเวอร์แสดงผลไม่ตรงกัน

หน้า

ไซต์นี้จะมี 3 หน้าที่แชร์ส่วนหัวร่วมกัน: หน้าดัชนีพร้อมรายการผลิตภัณฑ์ โดยการคลิกที่ผลิตภัณฑ์ก็จะถูกเพิ่มลงในรถเข็น; หน้าตะกร้าสินค้าที่จะแสดงเนื้อหาในตะกร้าและอนุญาตให้นำสินค้าออกจากตะกร้า หน้าเกี่ยวกับที่เป็นเพียงตัวยึดตำแหน่ง

เริ่มจากวิธีที่ง่ายที่สุดกันดีกว่า pages/about.js :

หน้านี้จะไม่ทำอะไรมากไปกว่านั้นรวมถึงส่วนหัวด้วย

หน้าหลักจะเป็น pages/index.js:

ในหน้านี้ เราวนผลิตภัณฑ์ของเราและพิมพ์ออกมาเป็นตาราง เราแนบการดำเนินการกับทุกผลิตภัณฑ์ด้วยการคลิก (addProduct(…)) เพื่อให้ทุกครั้งที่มีผลิตภัณฑ์ ถูกคลิก สินค้าถูกเพิ่ม (หรืออัปเดต) ลงในตะกร้าสินค้าผ่านชุด ฟังก์ชั่น ที่มีอยู่ใน useCarthook

หน้าตะกร้าสินค้าจะเป็น pages/cart.js:

หน้านี้จะวนซ้ำสินค้าในตะกร้าและแสดง โดยเพิ่มปุ่มเพื่อลบออกจากตะกร้า เช่นเดียวกับในองค์ประกอบ Header เราจำเป็นต้องใช้สถานะท้องถิ่นที่เต็มไปด้วยสถานะ Zustand หลังจากการให้น้ำ

หากตอนนี้คุณรันโครงการ:

npm run dev

และชี้เบราว์เซอร์ของคุณไปที่:

http://localhost:3000

คุณควรได้รับเว็บไซต์อีคอมเมิร์ซสมมุติของเรา การคลิกบนผลิตภัณฑ์จะเป็นการเพิ่มลงในรถเข็น (และการอัปเดตสถานะผลรวมและปริมาณจะอัปเดตส่วนหัว) การย้ายระหว่างหน้าต่างๆ จะไม่รีเซ็ตรถเข็น (รถเข็นจะถูกบันทึกใน localStarage) ; ไปที่หน้าตะกร้าสินค้า คุณสามารถลบสินค้าได้ (และอัปเดตส่วนหัวด้วย)

อะไรต่อไป

นี่เป็นเพียงตัวอย่างพื้นฐานของวิธีที่ Zustand สามารถใช้สำหรับการจัดการสถานะขั้นพื้นฐาน (และไม่ใช่ขั้นพื้นฐาน) แน่นอนว่านี่ไม่ใช่อีคอมเมิร์ซที่สมบูรณ์และการจัดการสถานะไม่ได้รับการปรับให้เหมาะสมสำหรับสภาพแวดล้อมการใช้งานจริง อย่างไรก็ตาม สิ่งนี้สามารถใช้เป็นจุดเริ่มต้นได้ โดยเฉพาะอย่างยิ่งสำหรับผู้พัฒนาที่ต้องการรวมเข้ากับโปรเจ็กต์ Nextjs

คุณสามารถสนับสนุนงานของฉันได้โดย ซื้อกาแฟให้ฉัน