เครื่องมือการจัดการสถานะปฏิกิริยาที่ดีที่สุดสำหรับแอปพลิเคชันระดับองค์กร

เผยแพร่แล้ว: 2022-03-11

นักพัฒนาแอปพลิเคชัน React ระดับองค์กรทราบดีว่าการจัดการสถานะมีความสำคัญต่อประสบการณ์ผู้ใช้ปลายทางที่สอดคล้องกันอย่างไร

อย่างไรก็ตาม ผู้ใช้ไม่ใช่คนเดียวที่ได้รับผลกระทบจากการจัดการของรัฐ นักพัฒนา React สร้างและรักษาสถานะ พวกเขาต้องการการจัดการสถานะที่เรียบง่าย ขยายได้ และเป็นปรมาณู React ได้ย้ายไปในทิศทางนี้โดยแนะนำตะขอ

ปัญหาอาจเกิดขึ้นเมื่อมีการแบ่งปันสถานะระหว่างองค์ประกอบต่างๆ วิศวกรต้องหาเครื่องมือและไลบรารีที่เหมาะสมกับความต้องการของตน แต่ในขณะเดียวกันก็ต้องมีคุณสมบัติตรงตามมาตรฐานระดับสูงที่จำเป็นสำหรับแอประดับองค์กร

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

ความสามารถในการจัดการสถานะปฏิกิริยาในตัว

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

แม้ว่าทั้งหมดนี้เป็นไปได้ในทางทฤษฎีกับบริบท แต่ก็ต้องการโซลูชันที่กำหนดเองซึ่งต้องใช้เวลาในการตั้งค่า สนับสนุน และปรับให้เหมาะสม ข้อได้เปรียบเพียงอย่างเดียวของบริบทคือมันไม่ได้ขึ้นอยู่กับไลบรารีของบุคคลที่สาม แต่นั่นไม่สามารถเกินดุลความพยายามในการรักษาแนวทางนี้

นอกจากนี้ Sebastian Markbage สมาชิกในทีม React ได้กล่าวว่า Context API ใหม่ไม่ได้สร้างและปรับให้เหมาะสมสำหรับการอัปเดตความถี่สูง แต่สำหรับการอัปเดตความถี่ต่ำเช่นการอัปเดตธีมและการจัดการการตรวจสอบ

การตรวจสอบห้องสมุดที่มีอยู่

มีเครื่องมือการจัดการสถานะมากมายบน GitHub (เช่น Redux, MobX, Akita, Recoil และ Zusstand) อย่างไรก็ตาม การพิจารณาแต่ละรายการจะนำไปสู่การค้นคว้าและเปรียบเทียบอย่างไม่รู้จบ นั่นเป็นเหตุผลที่ฉันจำกัดการเลือกของฉันให้เหลือเพียงคู่แข่งหลักสามรายโดยพิจารณาจาก ความนิยม การใช้งาน และ การดูแลรักษา

เพื่อให้การเปรียบเทียบชัดเจน ฉันจะใช้แอตทริบิวต์คุณภาพต่อไปนี้:

  • การใช้งาน
  • การบำรุงรักษา
  • ผลงาน
  • ความสามารถในการทดสอบ
  • ความสามารถในการปรับขนาด (ทำงานได้อย่างมีประสิทธิภาพเช่นเดียวกันในสถานะที่ใหญ่กว่า)
  • ความสามารถในการปรับเปลี่ยนได้
  • การนำกลับมาใช้ใหม่
  • ระบบนิเวศ (มีเครื่องมือช่วยเหลือที่หลากหลายเพื่อขยายการทำงาน)
  • ชุมชน (มีผู้ใช้จำนวนมากและคำถามของพวกเขาได้รับคำตอบบนเว็บ)
  • การพกพา (สามารถใช้กับไลบรารี/เฟรมเวิร์กอื่นที่ไม่ใช่ React)

Redux

Redux เป็นคอนเทนเนอร์ของรัฐที่สร้างขึ้นในปี 2558 ซึ่งได้รับความนิยมอย่างมากเนื่องจาก:

  • ไม่มีทางเลือกอื่นอย่างจริงจังเมื่อเปิดตัว
  • มันให้การแยกระหว่างรัฐและการกระทำ
  • เวทมนตร์ react-redux เปิดใช้งานการเชื่อมต่อสถานะตรงไปตรงมา
  • ผู้ร่วมสร้างห้องสมุดคือผู้พัฒนา Facebook และ Dan Abramov สมาชิกในทีมหลักของ React

แอนิเมชั่นแสดงความคืบหน้าของสถานะและการกระทำจากและไปยังตัวลดโดยใช้ Redux

คุณมี ร้านค้าระดับโลก ที่มีข้อมูลของคุณอยู่ เมื่อใดก็ตามที่คุณต้องการอัปเดตร้านค้า คุณต้องส่ง การดำเนินการ ไปที่ ตัวลด ตัวลดจะอัปเดตสถานะในลักษณะที่ไม่เปลี่ยนรูปทั้งนี้ขึ้นอยู่กับประเภทการดำเนินการ

ในการใช้ Redux กับ React คุณจะต้องสมัครสมาชิกส่วนประกอบเพื่ออัพเดตร้านค้าผ่าน react-redux

ตัวอย่าง Redux API

ส่วนพื้นฐานของ Redux ใน codebase ที่ทำให้แตกต่างจากเครื่องมืออื่นๆ คือ สไลซ์ มีตรรกะของการกระทำและตัวลดทั้งหมด

CodeSandbox

 // slices/counter.js import { createSlice } from "@reduxjs/toolkit"; export const slice = createSlice({ name: "counter", initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; } } }); export const actions = slice.actions; export const reducer = slice.reducer; // store.js import { configureStore } from "@reduxjs/toolkit"; import { reducer as counterReducer } from "./slices/counter"; export default configureStore({ reducer: { counter: counterReducer } }); // index.js import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import App from './App' import store from './store' ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) // App.js import React from "react"; import { useSelector, useDispatch } from "react-redux"; import { actions } from "./slices/counter"; const App = () => { const count = useSelector((state) => state.counter.value); const dispatch = useDispatch(); return ( <div> <div> <button onClick={() => dispatch(actions.increment())}>Increment</button> <span>{count}</span> <button onClick={() => dispatch(actions.decrement())}>Decrement</button> </div> </div> ); }; export default App;

คุณสมบัติคุณภาพ

  • การใช้งาน Redux กลายเป็นเรื่องง่ายด้วยการแนะนำแพ็คเกจชุดเครื่องมืออย่างเป็นทางการ คุณสร้างสไลซ์ (การรวมกันของสถานะเริ่มต้น ตัวลด และการดำเนินการ) ส่งต่อไปยังร้านค้า และเข้าถึงในส่วนประกอบผ่านตะขอ
  • การบำรุงรักษา Redux เป็นเรื่องง่าย ไม่จำเป็นต้องมีความรู้อย่างลึกซึ้งเพื่อทำความเข้าใจวิธีปรับปรุงหรือซ่อมแซมบางสิ่ง
  • ประสิทธิภาพการทำงาน ผู้มีอิทธิพลด้านประสิทธิภาพหลักกับ Redux คือวิศวกรซอฟต์แวร์ Redux เป็นเครื่องมือที่ตรงไปตรงมาโดยไม่มีตรรกะอะไรมาก หากคุณเห็นว่าการอัปเดตสถานะช้า คุณสามารถทำตามคำแนะนำอย่างเป็นทางการเพื่อทำให้อัปเดตเร็วขึ้นได้
  • ความสามารถใน การทดสอบ Redux ประกอบด้วยฟังก์ชันล้วนๆ (การกระทำและตัวลดขนาด) ทำให้เหมาะสำหรับการทดสอบหน่วย นอกจากนี้ยังมีกลไกในการเขียนการทดสอบการรวมที่ร้านค้า การดำเนินการ และตัวลดการทำงานร่วมกัน
  • ความสามารถใน การปรับ ขนาด ตามค่าเริ่มต้น Redux มีสถานะเดียว ทำให้ปรับขนาดได้ยาก อย่างไรก็ตาม มีไลบรารี redux-dynamic-modules ที่ช่วยให้สามารถสร้างตัวลดโมดูลและมิดเดิลแวร์ได้
  • การ ปรับเปลี่ยน การปรับแต่ง Redux เป็นเรื่องง่ายเพราะรองรับมิดเดิลแวร์
  • การนำกลับมาใช้ ใหม่ Redux เป็น framework ที่ไม่เชื่อเรื่องพระเจ้า ดังนั้นจึงสามารถใช้ซ้ำได้ดีมาก
  • ระบบนิเวศ . Redux นำเสนอระบบนิเวศขนาดยักษ์ของส่วนเสริม ไลบรารี และเครื่องมือที่เป็นประโยชน์
  • ชุมชน . Redux ซึ่งเป็นไลบรารีการจัดการของรัฐที่เก่าแก่ที่สุดในการเปรียบเทียบของเรา ได้รวบรวมชุมชนขนาดใหญ่ที่มีฐานความรู้ที่สำคัญ มีคำถามประมาณ 30,000 (~ 19,000 คำตอบ) พร้อมแท็ก redux ใน Stack Overflow
  • ชีพจร . Redux ได้รับการปรับปรุงและบำรุงรักษาอย่างสม่ำเสมอ

MobX

MobX เป็นห้องสมุดที่ค่อนข้างเก่าอีกแห่งที่มีดาว 23,000 ดวงบน GitHub สิ่งที่ทำให้แตกต่างจาก Redux คือเป็นไปตามกระบวนทัศน์ OOP และใช้สิ่งที่สังเกตได้ MobX ถูกสร้างขึ้นโดย Michel Weststrate และขณะนี้ได้รับการดูแลโดยกลุ่มผู้ที่ชื่นชอบโอเพ่นซอร์สด้วยความช่วยเหลือจาก Mendix ในบอสตัน

แผนภาพแสดงการจัดการสถานะโดยใช้ MobX จากการกระทำ ผ่านสถานะที่สังเกตได้และค่าที่คำนวณได้ ไปจนถึงผลข้างเคียง

ใน MobX คุณสร้างคลาส JavaScript ด้วยการเรียก makeObservable ภายใน Constructor ซึ่งเป็นที่ เก็บที่สังเกตได้ ของคุณ (คุณสามารถใช้ @observable decorator ถ้าคุณมีตัวโหลดที่เหมาะสม) จากนั้นคุณประกาศคุณสมบัติ (สถานะ) และวิธีการ ( การกระทำ และ ค่าที่คำนวณได้ ) ของคลาส ส่วนประกอบสมัครรับข้อมูลจากร้านค้าที่สังเกตได้นี้เพื่อเข้าถึงสถานะ ค่าที่คำนวณได้ และการดำเนินการ

คุณสมบัติที่สำคัญอีกประการของ MobX คือการกลายพันธุ์ อนุญาตให้อัปเดตสถานะอย่างเงียบ ๆ ในกรณีที่คุณต้องการหลีกเลี่ยงผลข้างเคียง

ตัวอย่าง MobX API

คุณลักษณะเฉพาะของ MobX คือคุณสร้างคลาส ES6 ที่เกือบจะบริสุทธิ์ด้วยเวทมนตร์ทั้งหมดที่ซ่อนอยู่ภายใต้ประทุน ต้องใช้โค้ดเฉพาะของไลบรารีน้อยกว่าเพื่อรักษาสมาธิในตรรกะ

CodeSandbox

 // stores/counter.js import { makeAutoObservable } from "mobx"; class CounterStore { value = 0; constructor() { makeAutoObservable(this); } increment() { this.value += 1; } decrement() { this.value -= 1; } } export default CounterStore; // index.js import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "mobx-react"; import App from "./App"; import CounterStore from "./stores/counter"; ReactDOM.render( <Provider counter={new CounterStore()}> <App /> </Provider>, document.getElementById("root") ); // App.js import React from "react"; import { inject, observer } from "mobx-react"; const App = inject((stores) => ({ counter: stores.counter }))( observer(({ counter }) => { return ( <div> <div> <button onClick={() => counter.increment()}>Increment</button> <span>{counter.value}</span> <button onClick={() => counter.decrement()}>Decrement</button> </div> </div> ); }) ); export default App;

คุณสมบัติคุณภาพ

  • การใช้งาน ร้านค้าที่สังเกตได้คือจุดเริ่มต้นเดียวสำหรับการจัดการของรัฐ มันทำให้การใช้งาน MobX เป็นเรื่องง่ายเพราะคุณมีที่เดียวในการแก้ไข
  • การบำรุงรักษา มันเป็นข้อเสียอย่างมาก หากไม่มีความรู้เกี่ยวกับ RxJS API คุณจะไม่สามารถบรรลุผลลัพธ์ที่ต้องการได้ การใช้ MobX ในทีมที่มีคุณสมบัติไม่ดีอาจนำไปสู่ปัญหาความไม่สอดคล้องกันของรัฐ
  • ประสิทธิภาพการทำงาน MobX ประกอบด้วยร้านค้าอิสระและช่วยให้คุณสามารถสมัครสมาชิกร้านเดียวที่คุณต้องการ มันมีประสิทธิภาพมาก
  • ความสามารถใน การทดสอบ ร้านค้าที่สังเกตได้คือออบเจ็กต์ JavaScript ธรรมดาที่มีฟังก์ชันตอบโต้ที่ซ่อนอยู่ภายใน การทดสอบเหมือนกับคลาส JavaScript อื่นๆ
  • ความสามารถใน การปรับ ขนาด ร้านค้าที่สังเกตได้จะถูกแยกออกอย่างมีเหตุมีผล ไม่มีปัญหาในการปรับขนาด MobX
  • การ ปรับเปลี่ยน MobX อนุญาตให้สร้างสิ่งที่สังเกตได้เองพร้อมพฤติกรรมที่ปรับเปลี่ยน นอกจากนี้ยังมีแนวคิดที่เรียกว่าปฏิกิริยา ปฏิกิริยาจำลองผลข้างเคียงโดยอัตโนมัติ สิ่งเหล่านี้ทำให้ MobX ปรับแต่งได้มาก
  • การนำกลับมาใช้ ใหม่ MobX นั้นไม่เชื่อเรื่องพระเจ้าของเฟรมเวิร์ก ดังนั้นจึงสามารถใช้ซ้ำได้ดีมาก
  • ระบบนิเวศ . มีส่วนขยายหลายร้อยรายการสำหรับ MobX
  • ชุมชน . MobX มีแฟน ๆ ที่ทุ่มเทมากมาย มีคำถามประมาณ 1,600 (~ 1,000 คำตอบ) พร้อมแท็ก mobx บน Stack Overflow
  • ชีพจร . MobX ได้รับการอัปเดตและบำรุงรักษาอย่างสม่ำเสมอ

หดตัว

การหดตัวเป็นผู้มาใหม่ซึ่งเป็นลูกสมุนล่าสุดของทีม React แนวคิดพื้นฐานที่อยู่เบื้องหลังคือการนำคุณลักษณะ React ที่ขาดหายไปไปใช้อย่างง่าย เช่น สถานะที่ใช้ร่วมกันและข้อมูลที่ได้รับ

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

การหดตัวสร้างขึ้นจากสองเงื่อนไข: atom และ selector อะตอมเป็นชิ้นส่วนของรัฐที่ใช้ร่วมกัน ส่วนประกอบสามารถสมัครสมาชิกอะตอมเพื่อรับ/ตั้งค่า

แผนภาพแสดงการจัดการสถานะด้วย Recoil แสดงให้เห็นว่าส่วนประกอบต่างๆ สามารถสมัครสมาชิกอะตอมเพื่อดึงหรือตั้งค่าได้อย่างไร

ดังที่คุณเห็นในภาพ เฉพาะส่วนประกอบที่สมัครรับข้อมูลเท่านั้นที่จะแสดงผลใหม่เมื่อค่ามีการเปลี่ยนแปลง มันทำให้การหดตัวมีประสิทธิภาพมาก

สิ่งที่ดีอีกอย่างที่ Recoil มีให้ตั้งแต่แกะกล่องคือ ตัวเลือก ตัวเลือกคือค่าที่รวบรวมจากอะตอมหรือตัวเลือกอื่นๆ สำหรับผู้บริโภค ไม่มีความแตกต่างระหว่างอะตอมและซีเล็คเตอร์ พวกเขาเพียงแค่สมัครใช้งานชิ้นส่วนที่มีปฏิกิริยาตอบสนองและใช้งาน

แผนภาพแสดงการใช้ตัวเลือกในการหดตัว ความสัมพันธ์กับอะตอม และการเปลี่ยนแปลงที่เกิดจากค่าต่างๆ

เมื่อใดก็ตามที่มีการเปลี่ยนแปลงอะตอม/ตัวเลือก ตัวเลือกที่ใช้ (เช่น สมัครเป็นสมาชิก) จะถูกประเมินใหม่

ตัวอย่าง Recoil API

รหัสของ Recoil นั้นแตกต่างจากคู่แข่งมาก มันขึ้นอยู่กับ React hooks และเน้นที่โครงสร้างสถานะมากกว่าการกลายพันธุ์สถานะนี้

CodeSandbox

 // atoms/counter.js import { atom } from "recoil"; const counterAtom = atom({ key: "counter", default: 0 }); export default counterAtom; // index.js import React from "react"; import ReactDOM from "react-dom"; import { RecoilRoot } from "recoil"; import App from "./App"; ReactDOM.render( <RecoilRoot> <App /> </RecoilRoot>, document.getElementById("root") ); // App.js import React from "react"; import { useRecoilState } from "recoil"; import counterAtom from "./atoms/counter"; const App = () => { const [count, setCount] = useRecoilState(counterAtom); return ( <div> <div> <button onClick={() => setCount(count + 1)}>Increment</button> <span>{count}</span> <button onClick={() => setCount(count - 1)}>Decrement</button> </div> </div> ); }; export default App;

คุณสมบัติคุณภาพ

  • การใช้งาน การหดตัวเป็นหนึ่งในเครื่องมือที่ง่ายที่สุดในการใช้งานเพราะมันทำงานเหมือนกับ useState ใน React
  • การบำรุงรักษา สิ่งที่คุณต้องทำใน Recoil คือการรักษาตัวเลือกและขอเกี่ยวภายในส่วนประกอบ—ให้คุณค่ามากขึ้น, ต้นแบบน้อยลง
  • ประสิทธิภาพการทำงาน Recoil สร้าง state tree นอก React ต้นไม้ประจำสถานะช่วยให้คุณได้รับและฟังสิ่งที่คุณต้องการ ไม่ใช่การเปลี่ยนแปลงของต้นไม้ทั้งต้น นอกจากนี้ยังปรับให้เหมาะสมอย่างดีภายใต้ประทุน
  • ความสามารถใน การทดสอบ การหดตัวเป็นกลไกสำหรับการทดสอบอะตอมและตัวเลือก
  • ความสามารถใน การปรับ ขนาด สถานะที่แยกออกเป็นชิ้นส่วนอิสระหลายส่วนทำให้เป็นผู้เล่นที่ดีในด้านความสามารถในการปรับขนาด
  • การ ปรับเปลี่ยน การหดตัวมีหน้าที่ในการจัดเก็บค่าและการรวมเท่านั้น ไม่มีการไหลของข้อมูลจึงสามารถปรับแต่งได้อย่างง่ายดาย
  • การนำกลับมาใช้ ใหม่ การหดตัวขึ้นอยู่กับ React ไม่สามารถใช้ซ้ำที่อื่นได้
  • ระบบนิเวศ . ไม่มีระบบนิเวศสำหรับการหดตัวในขณะนี้
  • ชุมชน . การหดตัวนั้นสดเกินไปที่จะมีชุมชนขนาดใหญ่ มีคำถามประมาณ 70 ข้อพร้อมแท็ก recoiljs ใน Stack Overflow
  • ชีพจร . การหดตัวมีการอัปเดตไม่บ่อยนัก (ผ่านไปหกเดือนระหว่างการอัปเดตล่าสุดสองครั้ง) นอกจากนี้ยังมีปัญหาเปิดมากมายใน GitHub

การเลือกเครื่องมือการจัดการสถานะปฏิกิริยาที่เหมาะสม

ไลบรารีการจัดการสถานะทั่วโลกของ React เหล่านี้ซ้อนกันอย่างไรเมื่อพูดถึงแอพระดับองค์กร

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

MobX และ Redux ไม่ได้แชร์ปัญหาเหล่านี้และผู้เล่นรายใหญ่ส่วนใหญ่ในตลาดก็ใช้ปัญหาเหล่านี้ สิ่งที่ทำให้พวกเขาแตกต่างจากกันคือเส้นโค้งการเรียนรู้ MobX ต้องการความเข้าใจพื้นฐานเกี่ยวกับการเขียนโปรแกรมเชิงโต้ตอบ หากวิศวกรที่เกี่ยวข้องในโครงการไม่มีทักษะเพียงพอ แอปพลิเคชันอาจลงเอยด้วยรหัสที่ไม่สอดคล้องกัน ปัญหาด้านประสิทธิภาพ และเวลาในการพัฒนาที่เพิ่มขึ้น MobX เป็นที่ยอมรับและจะตอบสนองความต้องการของคุณหากทีมของคุณตระหนักถึงปฏิกิริยา

Redux มีปัญหาบางอย่างเช่นกัน ส่วนใหญ่เกี่ยวกับความสามารถในการปรับขนาดและประสิทธิภาพ อย่างไรก็ตาม ต่างจาก MobX ตรงที่มีวิธีแก้ปัญหาที่พิสูจน์แล้วสำหรับปัญหาเหล่านี้

โดยคำนึงถึงข้อดีและข้อเสียทุกประการ และเมื่อพิจารณาจากประสบการณ์ส่วนตัวของฉัน ฉันแนะนำ Redux เป็นตัวเลือกที่ดีที่สุดสำหรับแอปพลิเคชัน React ระดับองค์กร