Redux by Sir Thet Khine

Side Note

Statement Management ဆိုတဲ့အတိုင်း State တွေကို Properties အနေနနဲ့ pass လုပ်ပေးတာမျိုး မရှိတော့ဘူး။​ Redux ရဲ့ connect ဆိုတဲ့ function သုံးပြီး Component တစ်ခုက လိုအပ်တဲ့ state နဲ့ action တွေကို ရှာဖွေတွဲထည့်ပေးလိမ့်မယ်။

ကြိုလုပ်ထားဖို့ လိုတာဆိုလို့

  • Reducer ( ဒါက Flutter ရဲ့ Provider မှာ state နဲ့ function တွေ ကြိုရေးထားသလိုပဲ)
  • Action : ဒါကတော့ operation_type နဲ့ payload ပါတဲ့ function တစ်ခုပဲ။

ဒီ action (Function) ကို view (component) က ခေါ်မယ်။ Reducer က လိုအပ်တဲ့ manipulation တွေ လုပ်ပေးမယ်။ Next State ကို ထုတ်ပေးမယ်။ ဒါဆို React က သက်ဆိုင်ရာ Component တွေကို ReRender ပြန်လုပ်ပေးမယ်။

နောက်ဆုံး Config လိုတာက


import { createStore } from 'redux';


var store = createStore(reducers);

function App() {
  return (
    <Provider store={store}>
        <App />
    </Provider>
  )
}

JS နဲ့ CRUD လုပ်တဲ့အကြောင်း။

// Sample array of objects
let data = [
    { id: 1, name: 'John' },
    { id: 2, name: 'Jane' },
    { id: 3, name: 'Bob' }
  ];
  
  // Create: Add a new object to the array
  const create = (array, newItem) => [...array, newItem];
  
  // Read (Retrieve): Find an object by ID
  const read = (array, id) => array.find(item => item.id === id);
  
  // Update: Update an existing object by ID
  const update = (array, id, updatedItem) => {
    return array.map(item => {
      if (item.id === id) {
        return { ...item, ...updatedItem };
      }
      return item;
    });
  };
  
  // Delete: Remove an object by ID
  const del = (array, id) => array.filter(item => item.id !== id);
  
  // Usage examples
  console.log('Original Data:', data);
  
  // Create
  data = create(data, { id: 4, name: 'Alice' });
  console.log('After Create:', data);
  
  // Read
  const itemToRead = read(data, 2);
  console.log('Read Item:', itemToRead);
  
  // Update
  data = update(data, 3, { name: 'Charlie' });
  console.log('After Update:', data);
  
  // Delete
  data = del(data, 1);
  console.log('After Delete:', data);

  /* */
  let oldObj = {
    key1 : "value1",
    key2 : "value2",
  }

  let updateObj = {
    key2 : "value two",
    key3 : "value 3"
  }

  let updatedObj  = {...oldObj, ...updateObj};

  console.log(oldObj);
  console.log(updateObj);
  console.log(updatedObj);

  /* obj မှာ Key နှစ်ခု specify လုပ်လိုက်ရင် နောက် key ကို အတည်ယူမယ် */
  

ဆရာ သက်ခိုင်ရေးထားတဲ့ Redux အကြောင်း။


Functional Programming မှာ Reduce က ဘယ်လိုအလုပ်လုပ်တာလဲ?


Introduction to Redux Part-1 ခုနောက်ပိုင်း SPA(Single Page Application) တွေ ဥပမာ React, Angular,Vue.js အစရှိတာတွေမှာ Redux ကို သုံးလာတယ်။ Redux က ဘာလဲဆိုရင် predictable state container ပေါ့။ အရင် MVC architecture pattern နဲ.ရေးတဲ့ application တွေမှာဆိုရင် application state သည် View ရဲ. action အများကြီးကနေ ပြောင်းလို.ရတယ်။ဥပမာ Button click ကနေ ပဲ model ကို ပြောင်းမလား အြ့တော့ state ကိုထိန်းရတာခက်တယ်။ အသေးစိတ်က ဒီမှာရေးထားတယ် MVC vs Flux https://web.facebook.com/thet.khine.587/posts/10207492502230240 အဲ့တာတွေကို ဖြေရှင်းဖို. Flux architecture based library ပေါ်လာတယ် Redux ပေါ့၊ Redux သည် Flux architecture ကိုအခြေခံပြီးထုတ်ထားတာ၊ ပိုရှင်းသွားတယ်။ State ဆိုတာ server ကနေရလာတဲ့ application data ရှိမယ် နောက် user ကနေ application အပေါ်မှာလုပ်နေတဲ့ action data တွေရှိမယ်၊ ဥပမာ ဖေ့ဘုတ်သုံးနေတယ် FB က React နဲ.ရေးထားတာ၊ ဘယ် သူနဲ.တော့စကားပြောနေတယ် Photo Ablum ကြည့်နေတာလား အဲ့တာတွေသည် action data, နောက် news feed ပြဖို.ဘာညာ အဲ့တာတွေကျတော့ application data။ အဲ့တော့ Application တခုရဲ. state ဆိုတာ server application data+ user action data အဲ့၂ ခုပေါင်းပေါ့။ ဘာလို. state management library ကိုသုံးလဲပေါ့၊ ဥပမာ Complex Application တွေမှာ state ကို component တွေကနေ ကြိုက်တဲ့နေရာကနေ ပြောင်းမယ် (MVC architecture လိုကောင်တွေမှာပေါ့) Component A ကလဲ stateA ကိုပြောင်းမယ် ComponentB ကလဲ stateA ကိုပြောင်းနိုင်တယ် အဲ့ကျ ဘယ်သူကပြောင်းလိုက်တာ ဆိုတာ လိုက်ရခက်လာတယ် trace, test , debug လုပ်ရတာခက်လာတယ်။ အဲ့တော့ Flux architecture ကိုအခြေခံထားတဲ့ Redux လိုကောင်မှာကျတော့ state ကိုတနေရာမှာပဲထားလိုက်တော့တယ်၊ နောက် state ကိုပြောင်းဖို. action တွေကိုလဲစုထားတယ် ၊ View Component တွေသည် state change ချင်ရင် Action တွေကိုခေါ်ရမယ် အဲ့တော့ state ပြောင်းတာလုပ်တာသည် action တွေအပေါ်မူတည်သွားတယ်။ Flow က လိုက်ရတာပိုရှင်းသွားတယ်၊ ဒီလိုဖြစ်သွားမယ် State+Action = Next State ဒီနေရာမှာ state ဆိုတာ todo list ဆိုပါစို.ဗျာ logically ဒီလို array ပေါ့ အဲ့တာဆို todo list ထဲ add တာရယ် remove တာရယ်ရှိမယ်။ state = [] todo_state + add_action => next state ဒါဆို todo state ကို add လုပ်မယ်ဆိုရင် to do item အသစ်ထပ်တိုးလာမယ်ပေါ့၊ ဒါသည် next state ပေါ့။ အဲ့တော့ မူလက ဘယ် state ရှိတယ် ဘယ် Action လုပ်မယ်ဆိုရင် ဘယ် state ပြောင်းမယ်ဆိုတာ trace ရ test ရပိုလွယ်လာတယ်။ Flow က ဒီလိုလာမယ် View->Action->Reducer->New State-> Rerender View ဥပမာ View က အများကြီးရှိမယ် ဒါပေမဲ့ Action ၁ ခုထဲကိုပဲဝိုင်းခေါ်တယ် ဒါဆို Action ကိုပဲကြည့်လိုက်ရင် ဘာလုပ်သွားတယ်ဆိုတာပိုရှင်းတာပေါ့၊ Redux မှာ state ကို store လို.သုံးတယ် Action ကတော့ ဒီလိုကောင်တွေပေါ့ let nextTodoId = 0; export const addTodo = text => ({ type: ‘ADD_TODO’, id: nextTodoId++, text }); action မှာအဓိက က ဘာလုပ်မှာလဲဆိုတဲ့ action type ဒီနေရာမှာ ADD_TODO ရယ် payload ရယ်ပါတယ်။ payload ကတော့ action ဖို.လိုတဲ့ parameter ပေါ့. Action တွေကိုဘယ်သူကခေါ်မှာလဲဆိုတော့ View ကနေခေါ်မှာ။ View ကနေ Action တော့ခေါ်ပြီ action ပေါ်မူတည်ပြီး state ကဘယ်လိုပြောင်းမှာတုန်းဆိုတော့ reducer ကိုသုံးရမှာ functional programming က reduce ဆိုတဲ့ function ပုံစံအလုပ်လုပ်လို. ဒါမို.Redux ဆိုပြီး နာမည်ပေးထားတာ။ Reducer Reducer ရဲ.အလုပ်က state အဟောင်းကနေ action ပေါ်မူတည်ပြီး state အသစ်ထုတ်တာပါပဲ။ ဒီနေရာမှာ သတိထားရမှာက reducer တွေသည် pure function တွေပဲ။ side effect ပါလို.မရဘူး ဥပမာ state.todo.push([something]) ဒါမျိုးမရဘူး မူလ state ကိုအသစ်ပြန်ဆောက်ရမယ် ဒါမှ React က state change တယ်ဆိုတာကိုသိနိုင်မှာ၊ အောက်က ကောင်က reducer ပေါ့၊ View ကနေ ခုနကရေးထားတဲ့ addToDo ကို payload ပေးပြီးခေါ်ကလိုက်ရင် redux ကနေ action ပေါ်မူတည်ပြီး reduce လုပ်သွားမယ်။ switch(action.type) { case ‘ADD_TODO’: return [ …state, { id: action.id, text: action.text } ]; default : return state; } ဒီနေရာမှာဆို return [ …state, { id: action.id, text: action.text } ]; ဆိုတဲ့ အဓိပ္ပာယ်က [] သည် array အသစ်ပြန်တာ … state သည်မူလရှိပြီးသား state ထဲ က item တွေကို တခုချင်းခွဲချတာ။ နောက် action မှာပါတဲ့ payload ကိုသုံးပြီး item အသစ်ထဲ့တယ်။ State အသစ်ရမယ် အဲ့ထဲမှာရှေ.က old state က data ရယ် နောက်အသစ်ထဲ့လိုက်တဲ့ item ပါမယ်၊ ဒါဆို new state ရပြီ အဲ့တာဆို React က state ပြောင်းတဲ့ View တွေ re render လုပ်မယ်။ နောက်တပိုင်းကျမှ Redux ကို code အရ configure လုပ်တာတွေ အလုပ်လုပ်ပုံတွေ ရေးပါ့မယ်

Introduction to Redux Part-2 ခုအပိုင်းကတော့ Redux ကို code example တွေ နဲ. ဘယ်လို setup ဆိုတာတွေရယ် main concept တွေရယ်ကိုပြောပေးမှာပါ။ Demo App ကတော့ ToDo app ပေါ့။ ToDo Item တွေထဲ့လို.ရမယ် remove လို.ရမယ်ပေါ့။ Code က ဒီမှာ online ကသင့်တော်ရာ ကောင်တွေ မှီငြမ်းပြီး structure ချကူးထားတယ်ဆိုပါစို.။ https://github.com/mrthetkhine/ReactReduxToDo ပထမဆုံး ToDo Item ထဲ့ဖို. .အတွက် View Component တခုရယ် နောက် ToDo list တွေပြဖို. component တခုရယ်လိုမယ်။ တကယ်တမ်း Redux ဖို.စ စဉ်းစားရင် store ကိုအရင် စဉ်းစားရတယ် ။နောက် interaction တွေဘယ်လိုလာမလဲ။ action တွေကဘာတွေပါမလဲ နောက် action တခုချင်းဆီမှာ store ကိုဘယ်လိုပြောင်းမလဲ။ တနည်း reducer တွေဘယ်လို ရေးမလဲပေါ့။ View အပိုင်းကတော့ ဘယ် Component တွေကို နေရာချမလဲဆိုတာ စဉ်းစားရတယ် ဒါကလဲ Component ဖွဲ.စည်းပုံ သည် data ဘယ်လိုသွားရင် အဆင်ပြေလဲပေါ်ပါထဲ့စဉ်းစားသင့်တယ် ဒါမှ နောက်ကျ ပြုရပြင်ရလွယ်မှာ။ နောက် Component တွေမှာ ဘယ်ကောင်တော့ pure ဖြစ်သင့်တယ် ဆိုတာမျိုးစဉ်းစားရမယ်။ Refactor လုပ်လို.ကောင်းအောင် reuse လုပ်လို.ရအောင် Component တွေကို စဉ်းစားရမယ်။ Project structure အရ src အောက်မှာ Component Action Reducers ဆိုပြီး folder တွေရှိပါမယ်။ Component သည် View တွေချည်းထားဖို.ပါ ဆိုင်ရာ application ကြီးရင် subfolder လေးတွေခွဲပေါ့။ Action သည် action တွေထားဖို.ပေါ့၊ နောက် Reducers ကတော့ ဆိုင်ရာ reducer တွေထားဖို. Reducer folder အောက်က index သည် store ကို configure လုပ်ဖို.အတွက် reducer တွေအားလုံးပေါင်းထားတာ (Application တခုမှာ redcuer တွေအများကြီး store ထဲကမှ တခုချင်းခွဲတာရှိနိုင်တယ် ဥပမာ ToDo ဖို.သက်သက် နောက် authentication ဖို.သက်သက် reducer တွေရှိနိုင်တယ် ) ဆိုင်ရာ store တွေနဲ.ပေါ့။ ခုနက Reducer တွေကိုသုံးပြီး store ကို create လုပ်တယ် အဲ့ကောင်ကို ပြီးရင် application ထဲထဲပေးလိုက်တယ်ပေါ့၊ ဒီလိုပေါ့၊ https://github.com/…/ReactRedu…/blob/master/src/index.js const store = createStore(allReducers); ReactDOM.render( <Provider store={store}> </Provider>, document.getElementById(‘root’) ); ဒါက ToDoRedcuer https://github.com/…/master/src/reducers/ToDoReducer.js const toDoReducer = (state = [], action) => { switch(action.type) { case ‘ADD_TODO’: return [ …state, { id: action.id, text: action.text } ]; case ‘REMOVE_TODO’: return state.filter(item=>item.id!=action.item.id) default : return state; } } export default toDoReducer; state သည် ToDoReducer ဘက်ကကြည့်ရင် ဒီနေရာမှာ todo item တွေသိမ်းဖို. array ပဲဖြစ်မယ်။ Redux သည် store (state)ကို design ချတဲ့အခါမှာ flat data structure ဖြစ်ရတယ် ရှင်းရှင်းပြောရင် array ပေါ့။ Redux store မှာပါတာတွေသည် array ဖြစ်ရမယ်၊ hierarchical tree structure ဆိုရင် array ဖြစ်အောင်ပြောင်းရမယ်။ ဒါမှ filter, map တို.နဲ.အဆင်ပြေမယ် reducer ရေးလို.ရမယ်။ နောက် Reducer သည် pure function ဖြစ်ရမယ်( state ကို assignment နဲ. state.something=”” အဲ့လိုပြင်တာမဟုတ်ပဲ။ new state object ဖြစ်အောင်လုပ်ရမယ်ပြောတာ) ဒါမှ react နောက်က ကောင်တွေသည် state ပြောင်းမပြောင်း reference equality နဲ.စစ်လို.ရမှာ မဟုတ်ရင် deep equality စစ်နေရတော့အဆင်မပြေဘူး။ ခုနက Store, reducer တွေ configure ပြီးရင် action တွေ store data ကို component တွေကယူသုံးမှာကို configure လုပ်ရမယ်။ ဥပမာ ဒီမှာကြည့် https://github.com/…/master/src/components/ToDoListing.js အဲ့လိုချိတ်ဖို.အတွက် connect ဆိုတာသုံးတယ် import { connect } from ‘react-redux’; သူ.ဖို.အောက်က ၂ ခုလိုတယ် const mapStateToProps = state => { return ({ todos: state.todos }) } const mapDispatchToProps = dispatch => { return { removeToDo: item => dispatch(removeToDo(item)) } } mapStateToProps ဆိုတာက store(state) ဖြစ်တဲ့ ကောင်ကို component properties အနေနဲ.သုံးမယ်ပြောတာ ခုကောင်မှာဆိုရင် state ရဲ. todos ဆိုတဲ့ကောင်ကို todos properties အနေနဲ.သုံးမယ်ပေါ့ ဒီကောင်အရ todos: state.todos ညာဘက်က state.todos ဘယ်ကရလဲဆိုရင် combineReducer မှာ configure လုပ်တဲ့ကောင် https://github.com/…/blob/master/src/reducers/index.js export default combineReducers({ todos: toDoReducer }) ဒီလိုရေးထားလို. ဘယ်ဘက်က todos ရေးထားလို. mapStateToProps မှာ todos ပြန်သုံးလို.ရတာ (ညာဘက်မှာပေါ့) နောက်တခု mapDispatchToProps ကတော့ action တွေကို properties အနေနဲ. ခေါ်သုံးလို.ရအောင်လုပ်ထားတာ။ action ခေါ်လိုက်ရင် တခါတည်း store dispatcher ကနေ reducer လှမ်းခိုင်း reducer လုပ်ပြီးရင် state ပြောင်းရင် react render လုပ်ဖို.က Redux framework ကလုပ်ပေးမယ်။ နောက်တခုက Ajax REST backend action တွေကို သက်သက် action အောက်မှာ ခွဲထားသင့်တယ် flow က Rest action ကိုခေါ်ရမယ် return ပြန်လာတဲ့ကောင်ကိုမှ တကယ့် Redux action အနေနဲ. payload အဖြစ်ပြောင်းပီး သုံးသင့်တယ်။

Written on September 4, 2023