Предисловие 🤔
-
React
это односторонний поток данных, данные проходят черезprops
Переход от родительского узла к дочернему узлу. Если на высшем уровнеprops
измененный,React
Все дочерние узлы будут перерисованы. Примечание ⚠️:props
доступен только для чтения (т.е. не может использоватьthis.props
Изменить напрямуюprops
), который используется для передачи данных и конфигурации по всему дереву компонентов. - Каждый компонент имеет свое
state
,state
а такжеprops
Разница в том, чтоstate
Существует только внутри компонентов. Примечание ⚠️: можно вызвать только из текущего компонентаthis.setState
Модификация методаstate
значение (не может быть изменено напрямуюthis.state
). - Видно, что есть два способа обновить подкомпоненты, один — изменить сам подкомпонент
state
значение, другой — обновить дочерний компонент, полученный от родительского компонента.this.props
значение для достижения обновления. - существует
React
В процессе разработки проекта большую часть времени нам нужно разрешить компонентам совместно использовать некоторые данные. В общем, мы можем передавать данные между компонентами (черезprops
) метод для достижения совместного использования данных, однако, когда данные должны передаваться между компонентами, которые не являются отношениями родитель-потомок, становится очень проблематично работать, и легко уменьшить читабельность кода.В настоящее время нам нужно использоватьstate
(статус) инструмент управления. - Общие инструменты управления состоянием включают
redux
,mobx
. из-заredux
Предоставляет всю архитектуру управления состоянием и имеет четкие ограничения, подходящие для использования в приложениях, разрабатываемых большим количеством людей. В этой статье описывается, какReact
используется в проектеredux
Осуществлять управление состоянием.
К делу 🥰
- Этот раздел в основном знакомит
redux
а такжеreact-router
Соответствующие базовые знания 📖 и соответствующая конфигурация 👩🏾💻.
redux
основная концепция
-
redux
Он подходит для сценариев с несколькими взаимодействиями и несколькими источниками данных. С точки зрения компонентов, если наше приложение имеет следующие сценарии, мы можем рассмотреть возможность его использования в проекте.redux
:- Состояние компонента, которым необходимо поделиться
- Состояние должно быть доступно везде
- Компонент должен изменить глобальное состояние
- Один компонент должен изменить состояние другого компонента
- Когда наше приложение соответствует сценариям, упомянутым выше, если мы не используем
redux
Или другие инструменты управления состоянием, которые не обрабатывают чтение и запись состояния по определенным правилам, удобочитаемость кода проекта будет сильно снижена, что не способствует повышению эффективности командной разработки.
- Как показано на фиг.
redux
поставив всеstate
Централизовано в верхней части компонента, можно гибко комбинировать всеstate
Распределите по всем компонентам по мере необходимости. -
redux
три принципа:- всего приложения
state
хранятся вobject tree
в иobject tree
существует только в единственномstore
in (это не означает использованиеredux
надо поставить всеstate
сохранитьredux
, компоненты могут по-прежнему поддерживать себяstate
). -
state
доступен только для чтения.state
изменения, приведет к представлению (view
)Изменение. Пользователь не может связатьсяstate
, только вид трогает, единственное изменениеstate
Способ состоит в том, чтобы вызвать в представленииaction
.action
это обычный объект, используемый для описания произошедшего события. - использовать
reducers
выполнитьstate
обновление.reducers
это чистая функция, которая принимаетaction
и текущийstate
В качестве аргумента вернуть новый по расчетуstate
, чтобы обновить представление.
- всего приложения
- Как показано на фиг.
redux
Рабочий процесс примерно такой:- Сначала пользователь передает
store.dispatch
метод испускаетaction
. - Потом,
store
автоматический вызовreducers
и передать два параметра: текущийstate
и получилaction
.reducers
вернется новыйstate
. - Наконец, когда
store
слушалstate
изменения, будет вызвана функция прослушивателя, чтобы вызвать повторную визуализацию представления.
- Сначала пользователь передает
- Поставьте картинку для углубления понимания ⚡⚡️⚡️️:
API
store
-
store
Есть место для сохранения данных, у всего приложения может быть только одноstore
. -
redux
поставкаcreateStore
Эта функция используется для созданияstore
для хранения всего приложенияstate
:
import { createStore } from 'redux';
const store = createStore(reducer, [preloadedState], enhancer);
- можно увидеть,
createStore
приниматьreducer
,исходныйstate
(необязательно) и энхансер в качестве аргумента, возвращает новыйstore
объект.
state
-
store
Объекты содержат все данные. Если вы хотите получить данные в определенный момент времени, вам нужноstore
Сделайте снимок. Сбор данных в этот момент времени называетсяstate
. - Если вы хотите получить текущий момент
state
, в состоянии пройтиstore.getState()
способ получения:
import { createStore } from 'redux';
const store = createStore(reducer, [preloadedState], enhancer);
const state = store.getState();
action
-
state
изменения приведут к изменению представления. Однако пользователи не имеют доступа кstate
, касается только представления. так,state
Изменения должны быть инициированы представлением. -
action
это уведомление, выдаваемое представлением, уведомлениеstore
В настоящее времяstate
Это должно было измениться. -
action
является объектом. один из нихtype
обязательный атрибут, указывающий, чтоaction
Имя. Другие свойства могут быть установлены свободно, и у сообщества есть спецификация для справки:
const action = {
type: 'ADD_TODO',
payload: 'Learn Redux' // 可选属性
};
- Приведенный выше код определяет имя как
ADD_TODO
изaction
, данные, которые он несет,Learn Redux
.
Action Creator
-
view
Существует столько видов сообщений, сколько нужно отправитьaction
, если все от руки, то будет очень хлопотно. - Функция может быть определена для генерации
action
, эта функция называетсяAction Creator
, как в коде нижеaddTodo
функция:
const ADD_TODO = '添加 TODO';
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
const action = addTodo('Learn Redux');
-
redux-actions
это служебная библиотека, которая позволяет писатьredux
Управление состоянием стало проще. Эта библиотека предоставляетcreateAction
Метод используется для создания генератора действий:
import { createAction } from "redux-actions"
export const INCREMENT = 'INCREMENT'
export const increment = createAction(INCREMENT)
- Приведенный выше код определяет действие
INCREMENT
, затем черезcreateAction
создал соответствующийAction Creator
:- передача
increment()
вернется, когда{ type: 'INCREMENT' }
- передача
increment(10)
вернуть{ type: 'INCREMENT', payload: 10 }
- передача
store.dispatch()
-
store.dispatch()
вид испускаетaction
единственный метод, который принимаетaction
Объект как параметр:
import { createStore } from 'redux';
const store = createStore(reducer, [preloadedState], enhancer);
store.dispatch({
type: 'ADD_TODO',
payload: 'Learn Redux'
});
- комбинировать
Action Creator
Этот код может быть переписан следующим образом:
import { createStore } from 'redux';
import { createAction } from "redux-actions"
const store = createStore(reducer, [preloadedState], enhancer);
const ADD_TODO = 'ADD_TODO';
const add_todo = createAction('ADD_TODO'); // 创建 Action Creator
store.dispatch(add_todo('Learn Redux'));
reducer
-
store
получатьaction
Позднее появился новыйstate
, так что представление обновляется.state
Процесс расчета (обновления) выполняетсяreducer
выполнить. -
reducer
это функция, которая принимаетaction
и текущийstate
В качестве параметра и возвращает новыйstate
:
const reducer = function (state, action) {
// ...
return new_state;
};
- Для реализации вызова
store.dispatch
метод выполняется автоматическиreducer
функция, которую необходимо создатьstore
будетreducer
входящийcreateStore
метод:
import { createStore } from 'redux';
const reducer = function (state, action) {
// ...
return new_state;
};
const store = createStore(reducer);
- В приведенном выше коде
createStore
метод принимаетreducer
В качестве аргумента создайте новыйstore
. позже всякий раз, когда представление используетstore.dispatch
Отправитьstore
новенькийaction
, он автоматически вызоветreducer
функция, получать обновленияstate
. -
redux-actions
при условииhandleActions
способ обработки несколькихaction
:
// 使用方法:
// handleActions(reducerMap, defaultState)
import { handleActions } from 'redux-actions';
const initialState = {
counter: 0
};
const reducer = handleActions(
{
INCREMENT: (state, action) => ({
counter: state.counter + action.payload
}),
DECREMENT: (state, action) => ({
counter: state.counter - action.payload
})
},
initialState,
);
Разделить, объединить редукторы
- Как упоминалось ранее, в
react
В приложении может быть только одинstore
для хранения приложенийstate
.组件通过调用action
функция, передающая данные вreducer
,reducer
Обновите соответствующийstate
. - Для больших приложений
state
должно быть очень большим, поэтомуreducer
Также увеличивается сложность.
расколоть
- В этот момент вы можете рассмотреть
reducer
Разделить на несколько отдельных функций, и пусть каждая функция отвечает за независимое управлениеstate
часть.
сливаться
-
redux
при условииcombineReducers
Вспомогательная функция, преобразующая независимые децентрализованныеreducer
объединены в финалreducer
функцию, а затем создатьstore
так какcreateStore
передаются параметры. - В соответствии с потребностями бизнеса, мы можем поставить все суб
reducer
Поместите их в разные каталоги, затем единообразно внесите в один файл и, наконец, объедините объединенныеreducer
Экспорт:
// src/model/reducers.ts
import { combineReducers } from 'redux';
import UI from './UI/reducers';
import user from './user/reducers';
import content from './content/reducers';
const rootReducer = combineReducers({
UI,
user,
content,
});
export default rootReducer;
Промежуточное ПО и асинхронные операции
- правильно
redux
Говоря о синхронизации, мы имеем в виду, когда представление испускаетaction
после,reducer
Рассчитать немедленноstate
(оригиналredux
рабочий процесс), в то время как асинхронный относится кaction
После того, как он выпущен, он будет выполнен через определенный период времениreducer
. - Синхронизация обычно происходит в нативном
redux
, тогда как в большинстве практических сценариев требуется больше асинхронных операций:action
После отправки, после вводаreducer
Асинхронная задача должна быть выполнена раньше, например, отправкаajax
Получив данные после запроса, введитеreducer
выполнять расчеты иstate
обновить. - видимо родной
redux
Асинхронные операции не поддерживаются, что требует нового инструмента — промежуточного ПО (middleware) для работы с данным бизнес-сценарием. По сути, промежуточное ПОstore.dispatch
метод был расширен. - Промежуточное ПО предоставляется по адресу
action
После начала, прибывreducer
Предыдущая точка расширения: т.е. черезstore.dispatch
метод выданaction
Он будет проходить через каждое промежуточное программное обеспечение по очереди и, наконец, придёт кreducer
. - Мы можем использовать промежуточное программное обеспечение для ведения журнала (
redux-logger
), создавать отчеты о сбоях (писать свои собственныеcrashReporter
), вызвать асинхронный интерфейс (redux-saga
) или маршрут (connected-react-router
) и так далее. -
redux
обеспечивает роднойapplyMiddleware
метод, его роль заключается в формировании массива всех промежуточных программ и их последовательном выполнении. Если вы хотите использоватьredux-logger
Для реализации функции ведения журнала используется следующее:
import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
const logger = createLogger();
const store = createStore(
reducer,
applyMiddleware(logger)
);
- Если имеется несколько промежуточных программ, передайте промежуточные программы последовательно в качестве параметров.
applyMiddleware
В методе:
import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
import createSagaMiddleware from 'redux-saga';
const logger = createLogger(); // 日志记录
const sagaMiddleware = createSagaMiddleware(); // 调用异步接口
let middleware = [sagaMiddleware];
middleware.push(logger);
const store = createStore(
reducer,
// 可传initial_state
applyMiddleware(...middleware)
);
- Примечание ⚠️:
-
createStore
Метод может принимать начальное состояние всего приложения в качестве параметра (необязательно).Если начальное состояние передается,applyMiddleware
требуется в качестве третьего параметра. - Некоторое промежуточное программное обеспечение имеет требования к порядку, проверьте документацию перед использованием (например,
redux-logger
Обязательно поставьте его в конце, иначе вывод будет неверным).
-
react-redux
Введение концепции
- описано в предыдущем разделе
redux
сам по себе является комбинируемымreact
,vue
,angular
даже роднойjavaScript
Государственная библиотека, используемая приложением. - чтобы
redux
помогите нам управлятьreact
состояние приложения, вам нужно поставитьredux
а такжеreact
подключение, официально предоставлено react-reduxбиблиотека (эта библиотека не является обязательной, или вы можете использовать толькоredux
). -
react-redux
Разделите все компоненты на две категории: компоненты пользовательского интерфейса и компоненты-контейнеры:- Компоненты пользовательского интерфейса отвечают только за отрисовку пользовательского интерфейса и не содержат состояние (
this.state
), все данныеthis.props
предоставляется без использования каких-либоredux
API. - Компоненты контейнера отвечают за управление данными и бизнес-логикой, включая состояние (
this.state
), быть пригодным для использованияredux
API.
- Компоненты пользовательского интерфейса отвечают только за отрисовку пользовательского интерфейса и не содержат состояние (
- Короче говоря, компонент-контейнер действует как родительский компонент компонента пользовательского интерфейса и отвечает за связь с внешним миром, передачу данных через
props
Передается компонентам пользовательского интерфейса для визуализации представления. -
react-redux
Оговаривается, что все компоненты пользовательского интерфейса предоставляются пользователем, а компоненты контейнера — пользователем.react-redux
Генерируется автоматически. Другими словами, пользователь отвечает за визуальный слой, а управление состоянием полностью передано ему.react-redux
.
API
Подключите метод
-
react-redux
при условииconnect
метод для создания компонентов контейнера из компонентов пользовательского интерфейса:
import { connect } from 'react-redux'
class Dashboard extends React.Component {
...
// 组件内部可以获取 this.props.loading 的值
}
const mapStateToProps = (state) => {
return {
loading: state.loading,
}
}
// 将通过 connect 方法自动生成的容器组件导出
export default connect(
mapStateToProps, // 可选
// mapDispatchToProps, // 可选
)(Dashboard)
- Как видно из приведенного выше кода,
connect
Метод принимает два необязательных параметра для определения бизнес-логики компонента-контейнера:-
mapStateToProps
Отвечает за входную логику, собираетсяstate
Сопоставляется с параметрами, переданными в компоненты пользовательского интерфейса (props
) -
mapDispatchToProps
Отвечает за логику вывода, то есть за отображение пользовательских операций над компонентами пользовательского интерфейса вaction
-
- Примечание ⚠️: Когда
connect
Когда метод не передает никаких параметров, сгенерированный компонент-контейнер можно рассматривать только как простую оболочку для компонента пользовательского интерфейса без какой-либо бизнес-логики:- пропускать
mapStateToProps
параметры, компоненты пользовательского интерфейса не будут подписыватьсяstore
,Прямо сейчасstore
Обновление компонента пользовательского интерфейса не приводит к обновлению. - пропускать
mapDispatchToProps
параметры, компоненты пользовательского интерфейса не будут рассматривать действия пользователя какaction
отправить данные наstore
, который нужно вызывать вручную в компонентеstore.dispatch
метод.
- пропускать
mapStateToProps
-
mapStateToProps
это функция, роль которой заключается в созданииstate
Объект (внешний) для компонента пользовательского интерфейсаprops
отображение объектов. Эта функция подписывается на все приложениеstore
,в любое времяstate
При его обновлении он будет выполняться автоматически, пересчитывая параметры компонента пользовательского интерфейса, тем самым запуская повторный рендеринг компонента пользовательского интерфейса. -
mapStateToProps
Первый параметр всегдаstate
объект, вы также можете использовать второй параметр (необязательный), представляющий компонент-контейнерprops
Объект:
// 容器组件的代码
// <Dashboard showType="SHOW_ALL">
// All
// </Dashboard>
const mapStateToProps = (state, ownProps) => {
return {
active: ownProps.showType === "SHOW_ALL",
loading: state.loading,
}
}
- использовать
ownProps
В качестве параметра, если параметры компонента контейнера изменятся, это также вызовет повторную визуализацию компонента пользовательского интерфейса.
mapDispatchToProps
-
mapDispatchToProps
даconnect
Второй параметр функции, используемый для создания параметров компонента пользовательского интерфейса дляstore.dispatch
Карта методов. - Поскольку в большинстве проектов используется
mapDispatchToProps
Он относительно невелик и подробно здесь обсуждаться не будет. оmapStateToProps
,mapDispatchToProps
а такжеconnect
Более подробные инструкции по использованию можно найти вДокументация.
Компонент поставщика
- использовать
connect
После того, как метод сгенерирует компонент-контейнер, вам нужно позволить компоненту-контейнеру получитьstate
объект для генерации параметров компонента пользовательского интерфейса. -
react-redux
при условииProvider
компонент, который позволяет компонентам контейнера получатьstate
, конкретное использование заключается в использованииProvider
Компонент обертывает корневой компонент проекта (например, приложение), поэтому все подкомпоненты корневого компонента могут быть получены по умолчанию.state
Объект:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import { store } from './store/configureStore';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'),
);
react-router
-
react-router
это завершеноreact
решение для маршрутизации, оно сохраняетUI
а такжеURL
синхронизация. В проекте мы используем последниеv4
Версия. - Следует отметить ⚠️, что его не следует устанавливать непосредственно во время разработки.
react-router
, потому что 👉: вv4
в версииreact-router
делится на три пакета:react-router
,react-router-dom
а такжеreact-router-native
, они различаются следующим образом:-
react-router
: Предоставляет основные компоненты и функции маршрутизации. -
react-router-dom
: Предоставляет компоненты маршрутизации и функции, используемые браузером. -
react-router-native
:поставкаreact-native
Соответствует компонентам маршрутизации и функциям, используемым платформой.
-
- когда наш
react
Приложение использует обаreact-router
а такжеredux
, они могут быть дополнительно интегрированы для достижения:- Буду
router
данные сstore
для синхронизации и могут быть доступны изstore
доступrouter
данные, доступныеthis.props.dispatch
способ отправкиaction
. - пройти через
dispatch actions
Навигация, личное понимание доступноstore.dispatch(push('routerName'))
Переключайте маршруты. - существует
redux devtools
Поддерживает отладку перемещения во времени для изменений маршрута в файлах .
- Буду
- Для достижения вышеуказанных целей вы можете
connected-react-router
а такжеhistory
Две библиотеки реализованы, и шаги следующие:- при создании
store
файл для добавления конфигурации, включая созданиеhistory
объект, использованиеconnected-react-router
который предоставилconnectRouter
Методы иhistory
создание объектаroot reducer
,использоватьconnected-react-router
который предоставилrouterMiddleware
промежуточное ПО иhistory
реализация объектаdispatch actions
навигация.
import { connectRouter, routerMiddleware } from 'connected-react-router'; import createHistory from 'history/createBrowserHistory'; import { createStore, applyMiddleware } from 'redux'; import { createLogger } from 'redux-logger'; import createSagaMiddleware from 'redux-saga'; import reducer from '../model/reducers'; export const history = createHistory(); const sagaMiddleware = createSagaMiddleware(); // 调用异步接口 let middleware = [sagaMiddleware, routerMiddleware(history)]; const logger = createLogger(); // 日志记录 middleware.push(logger); const initialState = {}; const store = createStore( connectRouter(history)(reducer), initialState, applyMiddleware(...middleware) );
- в файле входа проекта
index.js
Добавьте конфигурацию в корневой компонент, в том числе с помощьюconnected-react-router
который предоставилConnectedRouter
Компонент оборачивает маршрут, который будетConnectedRouter
компонент какProvider
подгруппа , и будет вstore
создан вhistory
объект импортируется какprops
поступающее имуществоConnectedRouter
Компоненты:
import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { Provider } from 'react-redux' import { ConnectedRouter } from 'connected-react-router' import App from './App' import rootSaga from './model/sagas'; import { store, history } from './store/configureStore'; ReactDOM.render( <Provider store={store}> <ConnectedRouter history={history}> <App /> </ConnectedRouter> </Provider>, document.getElementById('root'), );
- при создании
- Вышеупомянутое сделано
react-router
а такжеredux
Глубокая интеграция ✌️.
Резюме 👀
- В этой статье описывается, как
React
используется в проектеredux
Осуществляется управление состоянием, вводятся соответствующие основы и показывается полный код. - Некоторые специальные настройки обычно выполняются в проекте до разработки бизнес-кода, что полезно для последующей разработки проекта.Подробнее см. 👉:Процесс настройки проекта react + typescript.
Если есть какие-либо упущения или ошибки в вышеуказанном содержании, пожалуйста, оставьте сообщение ✍️Укажите и продвигайтесь вперед вместе💪💪💪
Если вы считаете, что эта статья полезна для вас, 🏀🏀 оставьте свой драгоценный 👍