Learn-Redux

Thư viện 30 dòng giống Redux - F8


  1. View
  2. CreateStore
  3. Run

1. Nội dung

2. Lý thuyết

Todo App

2.1 Tìm hiểu cơ chế vận hành React + Redux

Redux Flow Redux Flow

Redux Flow

2.2 Dòng dữ liệu

Redux Flow Redux Flow

Redux Flow Redux Flow

3. Tìm hiểu ý nghĩa và Xây dựng các thành phần

3.1 VIEW

3.1.1 File index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Todo App</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
  <script type="module" src="./script.js"></script>
</html>

3.1.2 File script.js

const rootElement = document.querySelector('#root');
const cars = ['BMW', 'Porsche', 'Mercedes'];

const html = `
<h1>TODO List</h1>
<ul>
  ${cars.map((car) => `<li>${car}</li>`).join('')}
<ul>
`;
console.log(html);
rootElement.innerHTML = html;
const rootElement = document.querySelector('#root');
const cars = ['BMW', 'Porsche', 'Mercedes', true, undefined, null, NaN, false];
const isSucceeded = false;
const html = `
<h1>${isSucceeded} && TODO List</h1>
<ul>
  ${cars.map((car) => `<li>${car}</li>`).join('')}
<ul>
`;
console.log(html);
rootElement.innerHTML = html;

script

export default function html([first, ...values], ...strings) {
  return values
    .reduce(
      (acc, cur) => {
        return acc.concat(strings.shift(), cur);
      },
      [first]
    )
    .filter((x) => (x && x !== true) || x === 0)
    .join('');
}
import html from './core.js';
const cars = ['BMW', 'Porsche', 'Mercedes'];
const isSucceeded = false;

const output = html`
  <h1>${isSucceeded} && TODO List</h1>
  <ul>
    ${cars.map((car) => `<li>${car}</li>`)}
    <ul></ul>
  </ul>
`;

const rootElement = document.querySelector('#root');
rootElement.innerHTML = output;

4. Kiểm tra

// core.js LIBRARY
function html([first, ...strings], ...values) {
  return values
    .reduce((acc, cur) => acc.concat(cur, strings.shift()), [first])
    .filter((x) => (x && x !== true) || x === 0)
    .join('');
}

function createStore(dataAndAction) {
  let state = dataAndAction();
  const roots = new Map();

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

  return {
    // enter action from user: add, edit, delete...
    dispatch(action, ...args) {
      state = reducer(state, action, args);
      render();
    },

    // get data, action and use action to process data
    connect: function connect(
      selector = function selector(state) {
        return state;
      }
    ) {
      return function (component) {
        return function (props, ...args) {
          return component(Object.assign({}, props, selector(state), ...args));
        };
      };
    },

    // display data to user-interface
    attach(component, root) {
      roots.set(root, component);
      render();
    },
  };
}

// DATA
var init = {
  cars: ['toyota', 'honda', 'porsche'],
};

// reducer.js getDATA and createACTIONs
export default function reducer(action, state = init, ...args) {
  console.log(action);
  switch (action) {

    case 'ADD': // action add, edit, delete...
      let [newCar] = args;
      return {
        cars: [...state.cars, newCar],
      };
      break;
    case 'DEL': // action add, edit, delete...
      const index = args[0]
      console.log('args::', index,state);
      if (index > -1) {
        state.cars.splice(index, 1); // 2nd parameter means remove one item only
      }
      return state;
      break;
    default:
      return state;
  }
}

function reducer(state = init, action, args) {
  switch (action) {
    case 'ADD': // action add, edit, delete...
      const [newCar] = args;
      return {
        cars: [...state.cars, newCar],
      };

    default:
      return state;
  }
}

// store.js USING LIBRARY
const { attach, connect, dispatch } = createStore(reducer);
window.dispatch = dispatch;

// Cycle: dispatch -> connect -> attach -> dispatch -> connect -> ...

// App.js
var App = connect()(
  // using connect, explaining role of connect here

  function ({ cars }) {
    // using html
    return html`
      <ul>
        ${cars.map((car) => `<li>${car}</li>`)}
      </ul>
      <button onclick="dispatch('ADD', 'PORSCHE')">Add car</button>
    `;
    // using dispatch-global
  }
);

// script.js
attach(App, document.getElementById('root')); // using attach

// THE END
// Good luck! You can do it :D