Я создам небольшое приложение для простых рейтинговых вопросов. Это задумано как упражнение для React и Redux, так как я все еще не понимаю его.
➡️ Github Repo доступен здесь ⬅️
📄 Содержание
- Мотивация для этой статьи
- Модульность базы
- Добавление Redux
- Типы действий
- Редукторы
- Действия и Создатели действий
- Создать Redux Store
- Подключить тару к магазину
- Добавить еще один компонент в приложение Redux
- Реализовать уток
- Chrome Redux DevTools
«Все на практике».
- Пеле
Мотивация для этой статьи
Еще одно небольшое приложение для понимания Redux и React. Такое ощущение, что это сотое приложение, пытающееся понять Redux. Но 1 месяц без Redux, и вы снова начинаете практически ни с чего. Я такой: «Да, я слышал об этом» - и все. Действие, Создатели действий, Редукторы, Диспетчеризация, блабла. Слишком много вещей, чтобы понять: D Итак, еще раз ↗️
Модульность базы
Структурируйте компоненты так, чтобы они идеально вписывались в приложение Redux.
- компонент секундомера имеет собственное локальное состояние, не зависит от других компонентов
- компоненты статистики и счетчика зависят от других компонентов
- AddQuestionForm зависит от других компонентов и также содержит логическую информацию
- компоненты заголовка и вопроса
Модуляризация помогает
- разделить обязанности, что означает более легкое тестирование и отладку
- лучше масштабировать приложение и проще использовать Redux
- лучше организовать между командами
Добавление Redux
Типы действий
Решите, какие компоненты должны участвовать в магазине Redux. - ›В этом приложении для всех компонентов должны быть доступны только вопросы.
Узнайте, какие события происходят в вашем приложении для этого конкретного состояния. - ›В этом приложении это
- изменение счета
- добавление вопросов
- удаление вопросов
Редукторы
Редукторы - это чистые функции, которые изменяют состояние в соответствии с типом действия.
Функция reducer предоставляет различные операторы switch о том, как изменить состояние. (Никогда не меняйте само состояние! Это должна быть чистая функция! # Неизменяемость)
Например:
export default function Player(state = initialState, action) { switch (action.type) { case QuestionActionTypes.ADD_PLAYER: return [ ...state, { name: action.name, score: 0, }, ]; case QuestionActionTypes.REMOVE_QUESTION: return [...state.slice(0, action.index), ...state.sclice(action.index + 1)]; case QuestionActionTypes.UPDATE_QUESTION_SCORE: return state.map((question, index) => { if (index === action.index) { return { ...question, score: question.score + question.score, }; } return question; }); default: return state; } }
Действия и Создатели действий
Отправка действия в Redux
- создатели действий генерируют действие (действие = событие, которое приведет к изменению состояния)
- действие отправляется в магазин Redux
- редуктор передает действие компоненту и возвращает новое состояние
Например, для добавления вопроса:
export const addQuestion = name => ({ type: QuestionActionTypes.ADD_QUESTION, name, });
Создать Redux Store
Создайте хранилище в своем index.js, передав ему основной редуктор и оберните его вокруг компонента табло, чтобы предоставить хранилище всему приложению.
Подключите контейнер к магазину
- используйте
mapStateToProps
, чтобы присвоить состояние значению свойства - ›назначить состояние вопросов в качестве свойства - для автоматической отправки созданных действий используйте:
const {dispatch, questions} = this.props; const addQuestion = bindActionCreators(QuestionActionCreators.addQuestion, dispatch); const removeQuestion = bindActionCreators(QuestionActionCreators.removeQuestion, dispatch); const updateQuestionScore = bindActionCreators(QuestionActionCreators.updateQuestionScore, dispatch);
- обновите обработчики событий на компонентах соответственно (компоненты счетчика, вопроса и табло)
- компоненты заголовка и секундомера не нуждаются в изменениях, потому что они не участвуют в цикле Redux
Добавьте еще один компонент в приложение Redux
Теперь мы хотим отображать детали для каждого вопроса.
- добавить новый тип действия (выбрать вопрос)
- расширить редуктор новым корпусом переключателя и дополнительным состоянием
- добавить новый создатель действий для выбора вопроса
- создать новый bindActionCreator в компоненте табло
- обновить mapStateToProps с выбранным индексом вопроса
- создать компонент QuestionDetail для отображения деталей
- обновить обработчик событий в компоненте вопроса
➡️ Смотрите коммит с реализацией компонента detail на Github ⬅️
Реализовать уток
Для небольших приложений концепция уток может помочь быстрее разработать приложение Redux. По сути, вместо того, чтобы сохранять все модульное (действия, редукторы, actionCreators), мы также можем хранить их в одном файле, чтобы иметь лучший обзор.
Этот файл выглядит так:
// Actions const ADD_QUESTION = 'question/ADD_QUESTION'; const REMOVE_QUESTION = 'question/REMOVE_QUESTION'; const UPDATE_QUESTION_SCORE = 'question/UPDATE_QUESTION_SCORE'; const SELECT_QUESTION = 'question/SELECT_QUESTION'; // Reducers const initialState = { questions: [ { name: 'Do you like AI?', score: 31, created: '00:00', updated: '00:00', }, { name: 'Do you like Engineering?', score: 20, created: '00:00', updated: '00:00', }, { name: 'How many Redux Apps?', score: 50, created: '00:00', updated: '00:00', }, ], selectedQuestionIndex: -1, }; export default function Question(state = initialState, action) { const date = `${new Date().getHours()}:00`; switch (action.type) { case ADD_QUESTION: const addQuestionList = [ ...state.questions, { name: action.name, score: 0, created: date, }, ]; return { ...state, questions: addQuestionList, }; case REMOVE_QUESTION: const removeQuestionList = [ ...state.questions.slice(0, action.index), ...state.questions.slice(action.index + 1), ]; return { ...state, questions: removeQuestionList, }; case UPDATE_QUESTION_SCORE: const updateQuestionList = state.questions.map((question, index) => { if (index === action.index) { return { ...question, score: question.score + action.score, updated: date, }; } return question; }); return { ...state, questions: updateQuestionList, }; case SELECT_QUESTION: return { ...state, selectedQuestionIndex: action.index, }; default: return state; } } // ActionCreators export const addQuestion = name => ({ type: ADD_QUESTION, name, }); export const removeQuestion = index => ({ type: REMOVE_QUESTION, index, }); export const updateQuestionScore = (index, score) => ({ type: UPDATE_QUESTION_SCORE, index, score, }); export const selectQuestion = index => ({ type: SELECT_QUESTION, index, });
➡️ Смотрите коммит с реализацией уток на Github ⬅️
Инструменты разработчика Chrome Redux
- Загрузите Расширение Redux DevTools
- добавьте нужную строку кода в свой магазин
const store = createStore( QuestionReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), );
DevTools помогает разрабатывать и отлаживать ваше приложение Redux. Ознакомьтесь с этой статьей, чтобы узнать больше.
Если вы что-то узнали из этой статьи, дайте мне знать в комментариях или сердцах. Не забудьте подписаться на больше :)