Новое начало не за горами, финальный модуль буткемпа 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 выглядел одинаково, верно? Это потому, что они точно такие же, это работает из-за отношения сериализатора, фактическая учетная запись возвращается с обновленным списком принадлежащих ей транзакций.
Вы можете более подробно ознакомиться с остальным кодом, используемым для сборки этого приложения, здесь!