Learn-Redux

Ví dụ xử lý Selector cho State của Store


// reducer.js (thằng này có chức năng xử lí và đưa dữ liệu vào trong store)
const init = {
  cars: ['BMW'],
};

function reducer(state = init, action, args) {
  switch (action) {
    case 'ADD':
      const [newCar] = args;
      console.log({
        ...state,
        cars: [...state.cars, newCar],
      });
      return {
        ...state,
        cars: [...state.cars, newCar],
      };
      break;
    default:
      return state;
  }
}

// core.js // Bộ xử lí trung tâm
function html([first, ...strings], ...values) {
  // Hàm này gọi là template engine, hàm này xử lí một số lỗi linh tinh của html thôi
  return values
    .reduce((acc, cur) => acc.concat(cur, strings.shift()), [first])
    .filter((x) => (x && x !== true) || x === 0)
    .join('');
}

function createStore(reducer) {
  // Ham này tạo ra dữ liệu trong store thông qua reducer và các thao tác trên view
  let state = reducer();
  const roots = new Map();

  function render() {
    // render ra view
    for (const [root, component] of roots) {
      console.log(component);
      const output = component();
      root.innerHTML = output;
    }
  }

  return {
    // Hàm này nhận mấy cái dòng HTML của component để hiển thị ra view
    attach(component, root) {
      roots.set(root, component); // doi voi obj thuong thi gan luon, nhung voi Map thi dung phuon thuc set
      render();
    },

    connect(selector = (state) => state) {
      // props và args là một obj, nó là các key: value mà ta muốn đưa thêm vào store và đưa ra view
      return (component) =>
        (props, ...args) =>
          component(Object.assign({}, props, selector(state), ...args));
    },

    // Hàm này có tác dụng gửi thông tin đến reducer để xử lí dư liệu trong store và cả render ra view
    dispatch(action, ...args) {
      state = reducer(state, action, args);
      render();
    },
  };
}

// store.js // Thằng này chứa dữ liệu để đưa ra view thôi
const { attach, connect, dispatch } = createStore(reducer);

window.dispatch = dispatch;

// app.js // Ông này là để xử lí html để xuất khẩu thôi
const connector = connect();

// Hàm này có tác dụng tạo ra HTML đã qua xử lí để chuẩn bị cho xuất khẩu
function App({ cars }) {
  return html`
    <ul>
      ${cars.map((car) => `<li>${car}</li>`)}
    </ul>

    <button onclick="dispatch('ADD', 'Ferrari')">Add car</button>
  `;
}

connector(App);
// Thằng này các bạn dễ nhầm lần nè, chú ý trong bài, khi import App từ component/App.js
// thì thực ra là import connector(App) với tên là App chứ không phải là App đâu

// App đây không phải là App ở trên mà phải là connector(App)
attach(connector(App), document.getElementById('root'));