ในระบบนิเวศของแอปพลิเคชัน JavaScript ที่ซับซ้อนและหลากหลายขึ้นเรื่อย ๆ มีสถานะที่ต้องจัดการมากขึ้นกว่าเดิมไม่ว่าจะเป็นผู้ใช้ปัจจุบันรายการโพสต์ที่โหลดเป็นต้น
ชุดข้อมูลใด ๆ ที่ต้องการประวัติของเหตุการณ์ถือได้ว่าเป็นสถานะ สถานะการจัดการอาจเป็นเรื่องยากและเกิดข้อผิดพลาดได้ง่าย แต่การทำงานกับข้อมูลที่ไม่เปลี่ยนรูป (แทนที่จะเปลี่ยนแปลงได้) และเทคโนโลยีสนับสนุนบางอย่าง ได้แก่ Redux สำหรับวัตถุประสงค์ของบทความนี้ - สามารถช่วยได้มาก
ข้อมูลที่ไม่เปลี่ยนรูปมีข้อ จำกัด กล่าวคือไม่สามารถเปลี่ยนแปลงได้เมื่อสร้างขึ้นแล้ว แต่ยังมีประโยชน์มากมายโดยเฉพาะอย่างยิ่งในการอ้างอิงเทียบกับความเท่าเทียมกันของมูลค่าซึ่งสามารถเร่งความเร็วแอปพลิเคชันที่ต้องอาศัยการเปรียบเทียบข้อมูลบ่อยๆ (ตรวจสอบว่ามีบางสิ่งที่ต้องอัปเดตหรือไม่ , ตัวอย่างเช่น).
การใช้สถานะที่ไม่เปลี่ยนรูปทำให้เราสามารถเขียนโค้ดที่สามารถบอกได้อย่างรวดเร็วว่าสถานะมีการเปลี่ยนแปลงหรือไม่โดยไม่จำเป็นต้องทำการเปรียบเทียบซ้ำกับข้อมูลซึ่งโดยปกติจะเร็วกว่ามาก
บทความนี้จะกล่าวถึงแอปพลิเคชันที่ใช้งานได้จริงของ Redux เมื่อจัดการสถานะผ่านผู้สร้างแอ็คชั่นฟังก์ชั่นบริสุทธิ์ตัวลดที่ประกอบขึ้นการกระทำที่ไม่บริสุทธิ์ด้วย Redux-saga และ Redux Thunk และสุดท้ายคือการใช้ Redux กับ React ที่กล่าวว่ามีทางเลือกมากมายสำหรับ Redux เช่นไลบรารีที่ใช้ MobX, Relay และ Flux
ประเด็นสำคัญที่แยก Redux ออกจากคอนเทนเนอร์สถานะอื่น ๆ ส่วนใหญ่เช่น MobX, Relay และการใช้งาน Flux อื่น ๆ ส่วนใหญ่คือ Redux มีสถานะเดียวที่สามารถแก้ไขได้ผ่านทาง 'actions' (วัตถุ JavaScript ธรรมดา) ซึ่งจะถูกส่งไปยัง ร้าน Redux ที่เก็บข้อมูลอื่น ๆ ส่วนใหญ่มีสถานะอยู่ในส่วนประกอบของ React ทำให้คุณมีหลายร้านค้าและ / หรือใช้สถานะที่เปลี่ยนแปลงได้
สิ่งนี้จะทำให้ตัวลดขนาดของร้านค้าซึ่งเป็นฟังก์ชันบริสุทธิ์ที่ทำงานกับข้อมูลที่ไม่เปลี่ยนรูปเพื่อดำเนินการและอาจอัปเดตสถานะ กระบวนการนี้บังคับใช้การไหลของข้อมูลทิศทางเดียวซึ่งง่ายต่อการเข้าใจและกำหนดได้ง่ายขึ้น
เนื่องจากตัวลด Redux เป็นฟังก์ชันบริสุทธิ์ที่ทำงานบนข้อมูลที่ไม่เปลี่ยนรูปจึงมักจะสร้างเอาต์พุตเดียวกันโดยให้อินพุตเดียวกันทำให้ง่ายต่อการทดสอบ นี่คือตัวอย่างของตัวลด:
import Immutable from 'seamless-immutable' const initialState = Immutable([]) // create immutable array via seamless-immutable /** * a reducer takes a state (the current state) and an action object (a plain JavaScript object that was dispatched via dispatch(..) and potentially returns a new state. */ function addUserReducer(state = initialState, action) { if (action.type === 'USERS_ADD') { return state.concat(action.payload) } return state // note that a reducer MUST return a value } // somewhere else... store.dispatch({ type: 'USERS_ADD', payload: user }) // dispatch an action that causes the reducer to execute and add the user
การจัดการในฟังก์ชั่นบริสุทธิ์ช่วยให้ Redux รองรับกรณีการใช้งานจำนวนมากได้อย่างง่ายดายซึ่งโดยทั่วไปไม่สามารถทำได้อย่างง่ายดายด้วยสถานะการกลายพันธุ์เช่น:
ผู้สร้างแอคชั่นของ Redux ช่วยรักษาโค้ดให้สะอาดและทดสอบได้ โปรดจำไว้ว่า 'การกระทำ' ใน Redux ไม่มีอะไรมากไปกว่าออบเจ็กต์ JavaScript ธรรมดาที่อธิบายการกลายพันธุ์ที่ควรเกิดขึ้น ดังที่กล่าวไว้การเขียนวัตถุเดิมซ้ำแล้วซ้ำเล่าเป็นเรื่องซ้ำซากและเกิดข้อผิดพลาดได้ง่าย
ราสเบอร์รี่ pi โฮมเซิร์ฟเวอร์ 2018
ผู้สร้างการกระทำใน Redux เป็นเพียงฟังก์ชันตัวช่วยที่ส่งคืนวัตถุ JavaScript ธรรมดาที่อธิบายการกลายพันธุ์ ซึ่งจะช่วยลดรหัสซ้ำ ๆ และเก็บการกระทำทั้งหมดของคุณไว้ในที่เดียว:
export function usersFetched(users) { return { type: 'USERS_FETCHED', payload: users, } } export function usersFetchFailed(err) { return { type: 'USERS_FETCH_FAILED', payload: err, } } // reducer somewhere else... const initialState = Immutable([]) // create immutable array via seamless-immutable /** * a reducer takes a state (the current state) and an action object (a plain JavaScript object that was dispatched via dispatch(..) and potentially returns a new state. */ function usersFetchedReducer(state = initialState, action) { if (action.type === 'USERS_FETCHED') { return Immutable(action.payload) } return state // note that a reducer MUST return a value }
ในขณะที่ธรรมชาติของตัวลดขนาดและการดำเนินการทำให้ง่ายต่อการทดสอบโดยไม่มีไลบรารีตัวช่วยที่ไม่เปลี่ยนรูป แต่ก็ไม่มีสิ่งใดปกป้องคุณจากวัตถุที่กลายพันธุ์ซึ่งหมายความว่าการทดสอบตัวลดขนาดทั้งหมดของคุณจะต้องมีความแข็งแกร่งเป็นพิเศษ
ลองพิจารณาตัวอย่างโค้ดต่อไปนี้ของปัญหาที่คุณจะพบโดยไม่มีไลบรารีเพื่อปกป้องคุณ:
const initialState = [] function addUserReducer(state = initialState, action) { if (action.type === 'USERS_ADD') { state.push(action.payload) // NOTE: mutating action!! return state } return state // note that a reducer MUST return a value }
ในตัวอย่างโค้ดนี้การเดินทางข้ามเวลาจะเสียเนื่องจากสถานะก่อนหน้านี้จะเหมือนกับสถานะปัจจุบันส่วนประกอบที่บริสุทธิ์อาจไม่อัปเดต (หรือแสดงผลใหม่) เนื่องจากการอ้างอิงถึงสถานะไม่ได้เปลี่ยนแปลงแม้ว่าข้อมูลจะ มีการเปลี่ยนแปลงและการกลายพันธุ์นั้นยากที่จะหาเหตุผลได้
เซ็นเซอร์ความเร็วลมและทิศทาง Arduino
หากไม่มีไลบรารีที่ไม่เปลี่ยนรูปเราจะสูญเสียประโยชน์ทั้งหมดที่ Redux มอบให้ ดังนั้นจึงขอแนะนำอย่างยิ่งให้ใช้ไลบรารีตัวช่วยที่ไม่เปลี่ยนรูปเช่นไม่เปลี่ยนรูป js หรือไม่มีรอยต่อ - ไม่เปลี่ยนรูปโดยเฉพาะอย่างยิ่งเมื่อทำงานในทีมขนาดใหญ่โดยใช้หลายมือสัมผัสโค้ด
ไม่ว่าคุณจะใช้ไลบรารีใด Redux ก็จะทำงานเหมือนกัน ลองเปรียบเทียบข้อดีข้อเสียของทั้งสองอย่างเพื่อให้คุณสามารถเลือกข้อใดที่เหมาะสมที่สุดสำหรับกรณีการใช้งานของคุณ:
Immutable.js เป็นไลบรารีที่สร้างขึ้นโดย Facebook โดยมีรูปแบบการทำงานที่ใช้งานได้มากขึ้นในโครงสร้างข้อมูลเช่นแผนที่รายการชุดและลำดับ ไลบรารีของโครงสร้างข้อมูลถาวรที่ไม่เปลี่ยนรูปของมันจะทำการคัดลอกจำนวนน้อยที่สุดเท่าที่จะเป็นไปได้ในระหว่างสถานะต่างๆ
ข้อดี:
จุดด้อย:
ไม่มีรอยต่อ - ไม่เปลี่ยนรูปเป็นไลบรารีสำหรับข้อมูลที่ไม่เปลี่ยนรูปซึ่งเข้ากันได้แบบย้อนหลังจนถึง ES5
มันขึ้นอยู่กับฟังก์ชันการกำหนดคุณสมบัติ ES5 เช่น defineProperty(..)
เพื่อปิดใช้งานการกลายพันธุ์บนวัตถุ ด้วยเหตุนี้จึงเข้ากันได้กับไลบรารีที่มีอยู่เช่น lodash และ Ramda นอกจากนี้ยังสามารถปิดใช้งานในรุ่นการผลิตซึ่งอาจเพิ่มประสิทธิภาพอย่างมีนัยสำคัญ
ข้อดี:
จุดด้อย:
คุณสมบัติที่มีประโยชน์อีกอย่างของ Redux คือความสามารถในการเขียนตัวลดด้วยกันสิ่งนี้ช่วยให้คุณสร้างแอปพลิเคชั่นที่ซับซ้อนมากขึ้นและในแอปพลิเคชันที่มีขนาดใด ๆ ที่สามารถมองเห็นได้คุณจะมีสถานะหลายประเภทอย่างหลีกเลี่ยงไม่ได้ (ผู้ใช้ปัจจุบันรายการโพสต์ที่โหลดแล้ว ฯลฯ ) Redux สนับสนุน (และสนับสนุน) กรณีการใช้งานนี้โดยการให้ฟังก์ชัน combineReducers
:
import { combineReducers } from 'redux' import currentUserReducer from './currentUserReducer' import postsListReducer from './postsListReducer' export default combineReducers({ currentUser: currentUserReducer, postsList: postsListReducer, })
ด้วยรหัสด้านบนคุณสามารถมีส่วนประกอบที่ขึ้นอยู่กับ currentUser
และส่วนประกอบอื่นที่อาศัย postsList
นอกจากนี้ยังช่วยเพิ่มประสิทธิภาพเนื่องจากส่วนประกอบเดียวจะสมัครเฉพาะสาขาใด ๆ ของต้นไม้ที่เกี่ยวข้อง
โดยค่าเริ่มต้นคุณสามารถส่งวัตถุ JavaScript ธรรมดาไปยัง Redux ได้เท่านั้น อย่างไรก็ตามด้วยมิดเดิลแวร์ Redux สามารถรองรับการกระทำที่ไม่บริสุทธิ์เช่นการรับเวลาปัจจุบันการร้องขอเครือข่ายการเขียนไฟล์ลงในดิสก์และอื่น ๆ
'มิดเดิลแวร์' เป็นคำที่ใช้สำหรับฟังก์ชันที่สามารถสกัดกั้นการดำเนินการที่ถูกส่งออกไป เมื่อถูกดักฟังแล้วก็สามารถทำสิ่งต่างๆเช่นแปลงการกระทำหรือส่งการกระทำแบบอะซิงโครนัสได้เช่นเดียวกับมิดเดิลแวร์ในเฟรมเวิร์กอื่น ๆ (เช่น Express.js)
ไลบรารีมิดเดิลแวร์ทั่วไปสองไลบรารี ได้แก่ Redux Thunk และ Redux-saga Redux Thunk เขียนในรูปแบบที่จำเป็นในขณะที่ Redux-saga เขียนในรูปแบบการทำงาน ลองเปรียบเทียบทั้งสองอย่าง
Redux Thunk สนับสนุนการกระทำที่ไม่บริสุทธิ์ภายใน Redux โดยใช้ thunks ซึ่งเป็นฟังก์ชันที่ส่งคืนฟังก์ชัน chain-able อื่น ๆ ในการใช้ Redux-Thunk คุณต้องติดตั้งมิดเดิลแวร์ Redux Thunk กับร้านค้าก่อน:
import { createStore, applyMiddleware } from 'redux' import thunk from 'redux-thunk' const store = createStore( myRootReducer, applyMiddleware(thunk), // here, we apply the thunk middleware to R )
ตอนนี้เราสามารถดำเนินการที่ไม่บริสุทธิ์ (เช่นการเรียก API) โดยการส่ง thunk ไปที่ Redux store:
store.dispatch( dispatch => { return api.fetchUsers() .then(users => dispatch(usersFetched(users)) // usersFetched is a function that returns a plain JavaScript object (Action) .catch(err => dispatch(usersFetchError(err)) // same with usersFetchError } )
โปรดทราบว่าการใช้ thunks สามารถทำให้โค้ดของคุณทดสอบได้ยากและทำให้ยากต่อการหาเหตุผลผ่านโฟลว์โค้ด
Redux-saga รองรับการกระทำที่ไม่บริสุทธิ์ผ่านไฟล์ ES6 (ES2015) คุณลักษณะที่เรียกว่าเครื่องกำเนิดไฟฟ้าและห้องสมุดของตัวช่วยที่ใช้งานได้จริง / บริสุทธิ์ สิ่งที่ยอดเยี่ยมเกี่ยวกับเครื่องกำเนิดไฟฟ้าคือสามารถกลับมาทำงานต่อและหยุดชั่วคราวได้และสัญญา API ทำให้ทดสอบได้ง่ายมาก
มาดูกันว่าเราจะปรับปรุงความสามารถในการอ่านและการทดสอบของวิธี thunk ก่อนหน้านี้โดยใช้ sagas ได้อย่างไร!
ก่อนอื่นมาติดตั้งมิดเดิลแวร์ Redux-saga กับร้านของเรา:
import { createStore, applyMiddleware } from 'redux' import createSagaMiddleware from 'redux-saga' import rootReducer from './rootReducer' import rootSaga from './rootSaga' // create the saga middleware const sagaMiddleware = createSagaMiddleware() // mount the middleware to the store const store = createStore( rootReducer, applyMiddleware(sagaMiddleware), ) // run our saga! sagaMiddleware.run(rootSaga)
โปรดทราบว่า run(..)
ต้องเรียกใช้ฟังก์ชันด้วยเทพนิยายเพื่อเริ่มดำเนินการ
ตอนนี้มาสร้างเทพนิยายของเรา:
import { call, put, takeEvery } from 'redux-saga/effects' // these are saga effects we'll use export function *fetchUsers(action) { try { const users = yield call(api.fetchUsers) yield put(usersFetched(users)) } catch (err) { yield put(usersFetchFailed(err)) } } export default function *rootSaga() { yield takeEvery('USERS_FETCH', fetchUsers) }
เราได้กำหนดฟังก์ชันตัวสร้างสองฟังก์ชันหนึ่งฟังก์ชันที่ดึงรายชื่อผู้ใช้และ rootSaga
สังเกตว่าเราไม่ได้เรียก api.fetchUsers
โดยตรง แต่ให้ผลในวัตถุเรียกแทน เนื่องจาก Redux-saga สกัดกั้นวัตถุเรียกและเรียกใช้ฟังก์ชันที่มีอยู่ภายในเพื่อสร้างสภาพแวดล้อมที่บริสุทธิ์ (เท่าที่เครื่องกำเนิดไฟฟ้าของคุณเกี่ยวข้อง)
rootSaga
ให้การเรียกใช้ฟังก์ชันที่เรียกว่า takeEvery,
ซึ่งดำเนินการทุกอย่างที่ส่งด้วยประเภท USERS_FETCH
และเรียก fetchUsers
เทพนิยายกับการกระทำที่เกิดขึ้น อย่างที่เราเห็นสิ่งนี้สร้างแบบจำลองผลข้างเคียงที่คาดเดาได้สำหรับ Redux ซึ่งทำให้ง่ายต่อการทดสอบ!
มาดูกันว่าเครื่องกำเนิดไฟฟ้าทำให้การทดสอบ sagas เป็นเรื่องง่ายได้อย่างไร เราจะใช้ มอคค่า ในส่วนนี้เพื่อเรียกใช้การทดสอบหน่วยของเราและ ชัย สำหรับการยืนยัน
เนื่องจาก sagas ให้วัตถุ JavaScript ธรรมดาและทำงานภายในเครื่องกำเนิดไฟฟ้าเราจึงสามารถทดสอบได้อย่างง่ายดายว่าพวกมันมีพฤติกรรมที่ถูกต้องโดยไม่มีการล้อเลียนเลย! โปรดทราบว่า call
, take
, put
ฯลฯ เป็นเพียงวัตถุ JavaScript ธรรมดาที่ถูกดักจับโดยมิดเดิลแวร์ Redux-saga
กองทุนรวมการลงทุนอสังหาริมทรัพย์เอกชน
import { take, call } from 'redux-saga/effects' import { expect } from 'chai' import { rootSaga, fetchUsers } from '../rootSaga' describe('saga unit test', () => { it('should take every USERS_FETCH action', () => { const gen = rootSaga() // create our generator iterable expect(gen.next().value).to.be.eql(take('USERS_FETCH')) // assert the yield block does have the expected value expect(gen.next().done).to.be.equal(false) // assert that the generator loops infinitely }) it('should fetch the users if successful', () => { const gen = fetchUsers() expect(gen.next().value).to.be.eql(call(api.fetchUsers)) // expect that the call effect was yielded const users = [ user1, user2 ] // some mock response expect(gen.next(users).value).to.be.eql(put(usersFetched(users)) }) it('should fail if API fails', () => { const gen = fetchUsers() expect(gen.next().value).to.be.eql(call(api.fetchUsers)) // expect that the call effect was yielded const err = { message: 'authentication failed' } // some mock error expect(gen.throw(err).value).to.be.eql(put(usersFetchFailed(err)) }) })
แม้ว่า Redux จะไม่ได้เชื่อมโยงกับไลบรารีที่แสดงร่วมใด ๆ แต่ก็ใช้ได้ดีเป็นพิเศษกับ React.js เนื่องจากส่วนประกอบ React เป็นฟังก์ชันบริสุทธิ์ที่รับสถานะเป็นอินพุตและสร้าง DOM เสมือนเป็นเอาต์พุต
React-Redux เป็นไลบรารีตัวช่วยสำหรับ React และ Redux ที่กำจัดการทำงานหนักส่วนใหญ่ในการเชื่อมต่อทั้งสอง ในการใช้ React-Redux อย่างมีประสิทธิภาพสูงสุดเรามาดูแนวคิดของส่วนประกอบในการนำเสนอและส่วนประกอบคอนเทนเนอร์กัน
ส่วนประกอบในการนำเสนออธิบายว่าสิ่งต่างๆควรมีลักษณะอย่างไรโดยขึ้นอยู่กับอุปกรณ์ประกอบฉากในการแสดงผลเท่านั้น พวกเขาเรียกการเรียกกลับจากอุปกรณ์ประกอบฉากเพื่อส่งการดำเนินการ เขียนด้วยมือล้วนๆและไม่ได้เชื่อมโยงกับระบบการจัดการของรัฐเช่น Redux
สัญญาณใดต่อไปนี้บ่งบอกว่าทีมมีขนาดเล็กเกินไป
ในทางกลับกันส่วนประกอบของคอนเทนเนอร์จะอธิบายว่าสิ่งต่างๆควรทำงานอย่างไรตระหนักถึง Redux ส่งการดำเนินการ Redux โดยตรงเพื่อทำการกลายพันธุ์และโดยทั่วไปจะสร้างขึ้นโดย React-Redux พวกเขามักจะจับคู่กับส่วนประกอบในการนำเสนอซึ่งเป็นอุปกรณ์ประกอบฉาก
มาเขียนส่วนประกอบการนำเสนอและเชื่อมต่อกับ Redux ผ่าน React-Redux:
const HelloWorld = ({ count, onButtonClicked }) => ( Hello! You've clicked the button {count} times! Click me ) HelloWorld.propTypes = { count: PropTypes.number.isRequired, onButtonClicked: PropTypes.func.isRequired, }
โปรดทราบว่านี่เป็นส่วนประกอบที่ 'โง่' ซึ่งอาศัยอุปกรณ์ประกอบฉากในการทำงานอย่างสมบูรณ์ นี่เป็นสิ่งที่ดีเพราะมันทำให้ไฟล์ ส่วนประกอบของปฏิกิริยาทดสอบง่ายและง่ายต่อการเขียน . มาดูวิธีเชื่อมต่อคอมโพเนนต์นี้กับ Redux กันก่อน แต่ก่อนอื่นเรามาพูดถึงส่วนประกอบลำดับที่สูงกว่ากัน
React-Redux มีฟังก์ชันตัวช่วยที่เรียกว่า connect( .. )
ที่สร้างคอมโพเนนต์ลำดับที่สูงขึ้นจากคอมโพเนนต์การตอบสนองที่ 'โง่' ซึ่งรับรู้ถึง Redux
การตอบสนองเน้นความสามารถในการขยายและการใช้งานซ้ำได้ผ่านองค์ประกอบซึ่งก็คือเมื่อคุณห่อส่วนประกอบในส่วนประกอบอื่น ๆ การห่อส่วนประกอบเหล่านี้สามารถเปลี่ยนพฤติกรรมหรือเพิ่มฟังก์ชันการทำงานใหม่ได้ มาดูกันว่าเราจะสร้างส่วนประกอบที่มีลำดับสูงขึ้นได้อย่างไรจากองค์ประกอบการนำเสนอของเราที่ตระหนักถึง Redux ซึ่งเป็นส่วนประกอบคอนเทนเนอร์
วิธีการทำมีดังนี้
import { connect } from 'react-redux' const mapStateToProps = state => { // state is the state of our store // return the props that we want to use for our component return { count: state.count, } } const mapDispatchToProps = dispatch => { // dispatch is our store dispatch function // return the props that we want to use for our component return { onButtonClicked: () => { dispatch({ type: 'BUTTON_CLICKED' }) }, } } // create our enhancer function const enhancer = connect(mapStateToProps, mapDispatchToProps) // wrap our 'dumb' component with the enhancer const HelloWorldContainer = enhancer(HelloWorld) // and finally we export it export default HelloWorldContainer
โปรดทราบว่าเราได้กำหนดสองฟังก์ชันคือ mapStateToProps
และ mapDispatchToProps
.
mapStateToProps
เป็นฟังก์ชันบริสุทธิ์ของ (state: Object) ที่ส่งคืนวัตถุที่คำนวณจากสถานะ Redux วัตถุนี้จะรวมเข้ากับอุปกรณ์ประกอบฉากที่ส่งผ่านไปยังส่วนประกอบที่ห่อหุ้มไว้ สิ่งนี้เรียกอีกอย่างว่าตัวเลือกเนื่องจากจะเลือกบางส่วนของสถานะ Redux ที่จะรวมเข้ากับอุปกรณ์ประกอบฉากของส่วนประกอบ
mapDispatchToProps
ยังเป็นฟังก์ชันบริสุทธิ์ แต่เป็นหนึ่งใน (dispatch: (Action) => void) ที่ส่งคืนวัตถุที่คำนวณจากฟังก์ชัน Redux dispatch ในทำนองเดียวกันวัตถุนี้จะรวมเข้ากับอุปกรณ์ประกอบฉากที่ส่งผ่านไปยังส่วนประกอบที่ถูกห่อ
ตอนนี้ในการใช้ส่วนประกอบคอนเทนเนอร์ของเราเราต้องใช้ Provider
ส่วนประกอบใน React-Redux เพื่อบอกส่วนประกอบคอนเทนเนอร์ว่าจะใช้เก็บอะไร:
import { Provider } from 'react-redux' import { render } from 'react-dom' import store from './store' // where ever your Redux store resides import HelloWorld from './HelloWorld' render( ( ), document.getElementById('container') )
Provider
คอมโพเนนต์เผยแพร่การจัดเก็บไปยังส่วนประกอบย่อย ๆ ที่สมัครสมาชิกร้านค้า Redux ทำให้ทุกอย่างรวมอยู่ในที่เดียวและลดจุดผิดพลาดหรือการกลายพันธุ์!
ด้วยความรู้ใหม่เกี่ยวกับ Redux ไลบรารีที่รองรับจำนวนมากและการเชื่อมต่อเฟรมเวิร์กกับ React.js คุณสามารถ จำกัด จำนวนการกลายพันธุ์ในแอปพลิเคชันของคุณได้อย่างง่ายดายผ่านการควบคุมของรัฐ ในทางกลับกันการควบคุมสถานะที่แข็งแกร่งจะช่วยให้คุณเคลื่อนที่ได้เร็วขึ้นและสร้างฐานรหัสที่มั่นคงด้วยความมั่นใจมากขึ้น