В этой статье мы собираемся изучить реализацию Redux (популярный вариант Flux) с Derivable.

Redux против Derivable

Простите, что заголовок статьи вызывает кликабельность. Реализация Redux, о которой мы собираемся здесь поговорить, не будет полной, и в этом нет никакого смысла.

Сам Redux очень полезен для использования вместе с Derivable в его текущей форме: это будет темой следующей статьи. Итак, нет Redux vs. Derivable.

Конечно, встает вопрос о добавленной стоимости использования Derivable с Redux. Мы обсудим это позже.

Архитектура Redux

Архитектура Redux настолько проста в ретроспективе. Итак, мы собираемся просто показать реализацию:

import {atom, derivation} from 'derivable'
function createStore(reduce, initialState = {}) {
  let store = atom(initialState)
  return {
    store: derivation(() => store.get())
    dispatch: (action) => {
     let nextState = reduce(store.get(), action)
     store.set(nextState)
    }
  }
}

Это все, что требуется (10 LOC), чтобы реализовать шаблон архитектуры, подобный Redux, с помощью Derivable. Конечно, это чрезмерное упрощение: например, промежуточное ПО не поддерживается.

Затем мы могли бы использовать createApplication для определения приложения, передав ему начальное состояние и редуктор, который позаботится об обработке действий и превращении их в обновления состояния:

let {store, dispatch} = createApplication(
  function reduce(state, action) {
    if (action.type === 'ADD_TODO') {
      return {
        ...state,
        todoList: state.todoList.concat(action.text)
      }
    } else {
      throw new Error('unknown action type: ' + action.type)
    }
  },
  {todoList: []}
)
function addTodo(text) {
  dispatch({type: 'ADD_TODO', text})
}

Обратите внимание, что атом, который хранит состояние, предоставляется не напрямую, а через наследование и функцию dispatch (). Это запрещает прямые мутации состояний.

Привязки к React

Интересно то, что нам не нужны какие-то специальные привязки к React, мы можем повторно использовать React Derivable, который мы обсуждали в предыдущих статьях.

import React from 'react'
import {reactive} from 'react-derivable'
let TodoList = reactive(props => {
  let todoList = store.get().todoList
  return (
    <div>
      <ul>{todoList.map(todo => <li>{todo}</li>)}</ul>
      <button onClick={() => addTodo('new todo!')}>
        Add todo
      </button>
    </div>
  )
})

Это одно из преимуществ единого уровня управления реактивным состоянием: мы можем повторно использовать фрагменты кода между различными стратегиями управления состоянием.

Но Derivable дает еще одно преимущество при использовании его вместе с Redux: эффективный уровень запросов для состояния приложения. Об этом мы поговорим в следующей статье.