Новое начало не за горами, финальный модуль буткемпа SE подошел к концу. От изучения того, что такое IDE и как загрузить свою собственную локальную среду, чтобы я мог выполнять лабораторные работы, до изучения Ruby, SQL, Sinatra, Rails, JavaScript, React, Redux и создания таких вещей, как CLI, API, статические приложения для аутентификации пользователей и динамические приложения... какое путешествие!

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

Итак, давайте приступим к финальному проекту — приложению React и Redux с бэкендом Rails API. Я чувствовал себя намного увереннее при настройке этого API, так как это нужно было сделать для предыдущего модуля. На этот раз я использовал в своем бэкэнде одну вещь, которой раньше не было, — гем Active Model Serializer (AMS). Я решил попробовать это после того, как у меня возникли некоторые трудности с несколькими редукторами и функцией редукса combineReducers(), к которым я вернусь.

Позвольте мне сказать вам, что AMS сделал мою жизнь на 1000% проще, когда дело дошло до работы с моим редукционным потоком. Итак, есть две жемчужины, которые я рассмотрел здесь, обе они включены в учебную программу Learn.co, AMS и Fast JSON API, так почему же я выбрал AMS? Что ж, я проверил GitHub для Fast JSON API, и в верхней части файла чтения было написано: «Fast JSON API — ⚠️ Этот проект больше не поддерживается!!!! ⚠️». Я ни в коем случае не знаю, что лучше, AMS старше и, согласно их ридми, кажется медленнее, чем альтернативы, но эти предупреждающие смайлики отпугнули меня от Fast JSON API.

Я закончил тем, что следовал этому замечательному прохождению для AMS, которое мы изучаем, и продолжил генерировать свои сериализаторы в моем терминале прекрасным способом, который позволяет вам rails, rails g serializer Account и rails g serializer Transaction. Теперь у меня была папка сериализаторов внутри папки моего приложения, содержащая сериализаторы учетной записи и транзакций.

Просто добавляя атрибуты, которые я хочу передать в свой внешний интерфейс, и отношение has_many (это ключ), все мои данные передаются только с одним редюсером. Вот посмотрите на эти сериализаторы.

class AccountSerializer < ActiveModel::Serializer
  attributes :id, :name, :balance, :acc_type
  has_many :transactions
end

Обратите внимание на отношение has_many :transactions, по этой причине я использовал сериализатор и смог упростить свой поток редукции, используя только один редуктор, редуктор учетных записей, для моего приложения.

class TransactionSerializer < ActiveModel::Serializer
  attributes :id, :t_name, :description, :t_type, :t_amount, :account_id
end

А вот и обычный сериализатор транзакций.

Атрибуты в обоих будут атрибутами, отображаемыми через мой запрос на выборку из-за этого отношения has_many.

export function fetchAccounts(){
    return(dispatch) =>{
        fetch('http://localhost:3000/accounts')
        .then(resp => resp.json())
        .then(accounts => {
            dispatch({type: 'FETCH_ACCOUNTS', payload: accounts})
        })
    }
}

О, и угадайте, что... для рендеринга обеих моделей требуется только 1 выборка из-за этого отношения has_many :transactions в сериализаторе учетной записи! Я не уверен, могу ли я подчеркнуть это достаточно, это было сногсшибательно для меня!

Таким образом, вместо того, чтобы маневрировать некоторым кодом, чтобы построить и реализовать combineReducers(), добавить редуктор транзакций, действие fetch для отображения всех транзакций и создать компонент транзакций, импортирующий и вызывающий это действие для изменения/обновления состояния с использованием mapStateToProps, componentDidMount , и {connect} from 'react-redux'... мы сделали быстрый на redux и использовали AMS для прохождения транзакций с учетными записями в действии fetchAccounts.

Несмотря на то, что AMS оказалась полезной для моего проекта и позволила отображать все мои учетные записи и транзакции, связанные с каждой учетной записью, с помощью одного действия/редьюсера, combReducer() по-прежнему чрезвычайно полезен и должен использоваться в большинстве случаев при использовании нескольких редьюсеров. Случай оказался одним из исключений.

Вот пик того, как выглядит мой редуктор благодаря AMS с немного большей функциональностью, чем просто выборка данных.

export default function accountReducer(state = {accounts: []}, action) {
    switch(action.type){
        case "FETCH_ACCOUNTS":
            return {accounts: action.payload}
        case "ADD_ACCOUNT":
            return {...state, accounts: [...state.accounts, action.payload]}
        case "ADD_TRANSACTION":
            return {...state, accounts: state.accounts.map(account => {
                if (account.id === action.payload.id) {
                    return action.payload
                }
                else {
                    return account
                }
            })}
        case "DELETE_TRANSACTION":
            return {...state, accounts: state.accounts.map(account => {
                if (account.id === action.payload.id) {
                    return action.payload
                }
                else {
                    return account
                }
            })}
        default:
            return state
    }
}

Если вы заметили, случай с ADD_TRANSACTION и DELETE_TRANSACTION выглядел одинаково, верно? Это потому, что они точно такие же, это работает из-за отношения сериализатора, фактическая учетная запись возвращается с обновленным списком принадлежащих ей транзакций.

Вы можете более подробно ознакомиться с остальным кодом, используемым для сборки этого приложения, здесь!