React - Redux 七分钟速成
注意力!!!
概述
重制版
Redux基础知识
Redux模式
React 和 Redux(计数器应用)
何时使用 Redux
结论
注意力!!!
本文中的代码是 Redux官方文档 Redux.js.org中提到的 Redux 模式的有效实现。不过,Redux 还提供了一个增强型工具包,建议在使用 React 和 Redux 进行开发时使用该工具包。最终选择哪种方式完全取决于您自己。您可以点击链接了解更多关于reduxjs/toolkit 的信息。
概述
在本文中,我将介绍 Redux 的一些基本概念,以及如何使用 React 和 Redux 构建一个简单的应用程序(计数器应用程序)。
重制版
Redux是 JavaScript 应用的可预测状态容器。这意味着,无论应用内发生何种变化,包括数据和 UI 的变化,这些变化都会被包含在一个名为state的 JavaScript 对象中。state 通常被称为“单一数据源”,因为它永远不会被修改或改变,而是会被重新创建。有了单一数据源,我们就能更好地预测应用在特定时刻的状态。
Redux基础知识
在深入探讨应用程序之前,让我们先来了解一些 Redux 的基础知识。
状态
状态是一个 JavaScript 对象,它代表 Redux 应用的完整状态。它可以是一个包含单个值的简单对象,也可以是一个更复杂的对象。
{counter: 0}
整个应用程序都可以访问状态,状态由一个名为 store 的集中式容器进行管理。访问 store 的唯一方法是通过 dispatch 一个action。
行动
操作是对商店应如何改变状态的描述。
{
type: 'INCREMENT',
value: 5,
}
应用程序内部的变化由 action 的type属性来识别。所有 action 都具有 type 属性。type 属性告诉 store 如何响应并重新创建状态。状态的创建由reducer处理。
减速器
reducer 是一个 JavaScript 函数,它会根据某种操作类型创建一个新的状态。
const reducer = (state = initialState, action) => {
switch (action.type) {
case actionType.ADD:
return {
...state,
counter: state.counter + 1
}
}
return state;
}
Reducer 通常被称为纯 JavaScript 函数。纯 JavaScript 函数是指对于相同的输入,始终返回相同输出的函数。之所以称为纯函数,是因为它们具有可预测性,并且不包含任何副作用,例如网络或数据库调用。Reducer 最重要的任务是为store重新创建状态。
店铺
store是一个 JavaScript 对象,用于保存应用程序的状态。一个 Redux 应用中应该只有一个 store。
{
dispatch: Dispatch
getState: () => State
subscribe: (listener: () => void) => () => void
replaceReducer: (reducer: Reducer) => void
}
存储方法
dispatch(action):派遣行动getState()返回当前状态subscribe(listener)添加一个变更监听器replaceReducer(nextReducer):替换减速器
Redux模式
React 和 Redux(计数器应用)
在本节中,我将介绍如何使用 React 和 Redux 构建一个简单的计数器应用程序。要查看应用程序代码,请点击此处。
入门
首先,我将使用npx创建一个基本的 React 应用,并安装所需的依赖项:react-redux 和 redux。
npx create-react-app redux-practice
cd redux-practice
npm i react-redux redux
接下来,我将创建三个新目录来管理我的应用程序的文件。
mkdir src/store
mkdir src/containers
mkdir src/components
src/storeRedux store 需要 Reducer 和 actionssrc/containers- 连接到 Redux store 的组件src/components- 展示层组件
我将首先着手处理位于 store 目录中的 actions 和 reducers。
touch src/store/actions.js
touch src/store/reducers.js
首先,我将定义我的操作。为了简单起见,便于演示,这个应用程序的操作不会很多。
src/store/actions.js
export const ADD = 'ADD';
export const SUBTRACT = 'SUBTRACT';
接下来,我将创建 store 所需的 reducer 函数。
src/store/reducers.js
import * as actionType from './actions';
const initialState = {
counter: 0
}
const reducer = (state = initialState, action) => {
switch (action.type) {
case actionType.ADD:
return {
...state,
counter: state.counter + 1
}
case actionType.SUBTRACT:
return {
...state,
counter: state.counter - 1
}
default:
return state
}
}
export default reducer;
在上面的代码片段中,我从actions.js导入了所有 actions ,然后创建了一个 state 变量来初始化这个 reducer 的状态,并创建了我的 reducer 函数。这个 reducer 函数接受两个参数:state和 action。state 未初始化时,会被设置为 initialState;action会在 dispatch 一个 action 时传入。我会使用 switch state 来判断 action 的类型,并使用actions.js中的 actions来处理每种情况。
现在我已经创建了 reducer 和 actions,接下来要创建 store。store 应该创建在顶层组件中,在本例中是index.js。
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import reducer from './store/reducers';
import './index.css';
import App from './App';
const store = createStore(reducer);
ReactDOM.render(
<React.Fragment>
<Provider store={store}><App /></Provider>
</React.Fragment>,
document.getElementById('root')
);
在index.js文件中,我从 redux 导入了createStore,并从 react-redux 导入了Provider。我还导入了 createStore 函数所需的 reducer。createStore 函数接收 reducer 作为参数,并返回 redux store。我使用了 Provider,它有一个名为store 的prop ,我将上面创建的 store 传递给 Provider 的这个 prop。此时,整个 React 应用都可以访问 redux store 了。
接下来,我将创建两个组件来表示计数器应用程序。
mkdir src/components/CounterButton
mkdir src/components/CounterLabel
touch src/components/CounterButton/CounterButton.js
touch src/components/CounterLabel/CounterLabel.js
这些组件是展示组件,所以它们会非常简单。
计数器按钮.js
import React from 'react';
import './CounterButton.css';
function CounterButton(props) {
return (
<div className="CounterButton">
<button
type="button"
onClick={props.clicked}
className="btn btn-primary">
{props.label}
</button>
</div>
)
}
export default CounterButton;
CounterLabel.js
import React from 'react';
import './CounterLabel.css'
function CounterLabel(props) {
return (
<div className='CounterLabel'>
{props.value}
</div>
)
}
export default CounterLabel;
接下来,我将创建计数器组件,并将其连接到 redux store。
touch src/containers/Counter.js
Counter.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actionType from '../store/actions';
import CounterLabel from
'../components/CounterLabel/CounterLabel';
import CounterButton from
'../components/CounterButton/CounterButton';
import './Counter.css';
class Counter extends Component {
render() {
return (
<div className="Counter">
<CounterLabel value={this.props.ctr} />
<CounterButton
clicked={this.props.onAdd}
label="Add" />
<CounterButton
clicked={this.props.onSubtract}
label="Subtract" />
</div>
)
}
}
const mapStateToProps = state => {
return {
ctr: state.counter
}
}
const mapDispatchToProps = dispatch => {
return {
onAdd: () => dispatch({ type: actionType.ADD }),
onSubtract: () => dispatch({type: actionType.SUBTRACT})
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Counter);
在Counter.js文件中,我从react-redux包导入了 connect 函数,并在文件末尾直接在组件中使用它。connect 函数接受两个参数:第一个参数mapStateToProps,用于选择组件所需的状态;第二个参数mapDispatchToProps,用于将 action 分发到 store。onAdd和onSubtract函数作为 props 传递给 ControlButtons 组件,点击这些按钮时,会将各自的 action 分发到 store。至此,一个简单的计数器应用程序就完成了。
何时使用 Redux
本文中的应用示例非常简单,仅供学习参考。大多数情况下,这种规模的应用并不需要使用 Redux。状态管理系统更适合大型应用,因为大型应用的状态管理往往比较复杂难懂。以下是我从Academind的 Maxillian 那里了解到的关于何时使用 Redux 的一些要点。
- 本地 UI 状态 - 不推荐使用 Redux
- 持久化状态 - Redux 可用于存储您需要显示的数据
- 客户端状态 - 考虑使用 Redux
结论
一如既往,请多保重。如果您觉得这篇文章有用,请留下评分;如果您有任何疑问,请留言,我会尽快回复。
文章来源:https://dev.to/meddy672/react-redux-in-less-then-7-minutes-had


