您现在的位置是:网站首页> 编程资料编程资料
在 React 中使用 Redux 解决的问题小结_React_
2023-05-24
357人已围观
简介 在 React 中使用 Redux 解决的问题小结_React_
在 React 中使用 Redux 解决的问题
在 React 项目中未加入 Redux 时的问题
在 React 中组件通信的数据流是单向的,顶层组件可以通过 props 属性向下层组件传递数据,而下层组件不能直接向上层组件传递数据。要实现下层组件修改上层组件的数据,需要上层组件传递修改数据的方法到下层组件。当项目越来越大的时候,组件之间传递数据以及传递修改数据的方法变得越来越困难。

在 React 项目中加入 Redux 的好处
使用 Redux 管理数据,由于 Store 独立于组件,使得数据管理独立于组件,解决了组件与组件之间传递数据困难的问题。

React + Redux 安装 Redux
在 react 项目中使用 redux 要下载两个模块
npm install redux react-redux
React 中 Redux 的工作流程
在 React 中 Redux 的工作流程有些变化:
- 组件通过 dispatch 方法触发 Action
- Store 接收 Action 并将 Action 分发给 Reducer
- Reducer 根据 Action 类型对状态进行更改并将更改后的状态返回给 Store
- 组件订阅了 Store 中的状态,Store 中的状态更新会同步到组件

React 计数器案例
React 实现
创建项目安装模块
# 创建项目(React 17 版本) npx create-react-app myapp # 安装 redux cd myapp npm install redux
删掉无用的文件
├─ src │ ├─ App.css │ ├─ App.test.js │ ├─ index.css │ ├─ logo.svg │ ├─ reportWebVitals.js │ └─ setupTests.js
初步实现
// src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import { createStore } from 'redux' const initialState = { count: 0 } function reducer (state = initialState, action) { switch (action.type) { case 'increment': return { count: state.count + 1 } case 'decrement': return { count: state.count - 1 } default: return state } } const store = createStore(reducer) const increment = { type: 'increment' } const decrement = { type: 'decrement' } function Counter() { return {store.getState().count} } store.subscribe(() => { ReactDOM.render( , document.getElementById('root') ); }) console.log(store.getState()) ReactDOM.render( , document.getElementById('root') ); 使用 Redux
开发时我们会把组件写在单独的文件中,如果将 Counter 组件单独提取,就无法访问 store 对象以及一些其它的问题,所以需要使用 redux。
安装 react-redux
npm install react-redux
react-redux 用于让 react 和 redux 完美结合,它仅仅提供两个内容:
- Provider 组件
- 它可以将创建出来的 store 放到全局,允许所有组件访问
- 可以解决将组件存储在单独文件中时,访问 store
- connect 方法
- connect 方法会帮助订阅 store,当 store 中的状态发生变化,会重新渲染组件
- 解决了需要手动订阅更新组件状态
- connect 方法可以获取 store 中的状态,映射到组件的 props 属性中
- connect 方法可以获取 dispatch 方法,组件可以通过 props.dispatch访问

Provide 组件
- Provider 组件要包裹项目中所有的组件,也就是应该被放在最外层组件上
- Provider 通过 store 属性接收创建的 store 对象
connect 方法
- 首先调用 connect 方法
- 第一个参数是一个函数
- 函数接收的第一个参数,即组件中的状态 state
- 函数要返回一个对象,该对象定义的属性都会映射到组件的 props 属性中
- 第二个参数也是一个函数
- 函数接收的第一个参数,即 dispatch 方法
- 函数要返回一个对象,可以定义触发 Action 的方法,它们同样会被映射到组件的 props 属性中
- 返回一个方法
- 第一个参数是一个函数
- 继续调用返回的方法,并传递当前的组件
修改代码
// src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import { createStore } from 'redux' import Counter from './components/Counter' import { Provider } from 'react-redux' const initialState = { count: 0 } function reducer (state = initialState, action) { switch (action.type) { case 'increment': return { count: state.count + 1 } case 'decrement': return { count: state.count - 1 } default: return state } } const store = createStore(reducer) ReactDOM.render( // 通过 provider 组件将 store 放在了全局,供所有组件可以访问 , document.getElementById('root') ); 提取的 Counter 组件
// src/components/Counter.js import { connect } from 'react-redux' function Counter(props) { return {props.count} } const mapStateToProps = state => ({ count: state.count }) export default connect(mapStateToProps)(Counter) 使用 connect 第二个参数简化组件
// src/components/Counter.js import { connect } from 'react-redux' function Counter({count, increment, decrement}) { return {count} } const mapStateToProps = state => ({ count: state.count }) const mapDispatchToProps = dispatch => ({ increment () { dispatch({ type: 'increment' }) }, decrement () { dispatch({ type: 'decrement' }) } }) export default connect(mapStateToProps, mapDispatchToProps)(Counter) 使用 bindActionCreators 方法继续简化
触发 Action 的方法 increment 和 decrement 的内容基本是一样的,redux 提供 bindActionCreators 方法生成一个函数,来简化这种重复性代码。
- 参数
- actionCreators: 对象或返回对象的函数
- key是生成函数的名称
- value是一个返回 Action 的函数
- dispatch: 需传递Store 的 dispatch 方法
- actionCreators: 对象或返回对象的函数
- 返回一个对象,同 connect 接收的第二个参数
// src/components/Counter.js import { connect } from 'react-redux' import { bindActionCreators } from 'redux' function Counter({count, increment, decrement}) { return {count} } const mapStateToProps = state => ({ count: state.count }) const mapDispatchToProps = dispatch => ({ ...bindActionCreators({ increment() { return { type: 'increment' } }, decrement() { return { type: 'decrement' } } }, dispatch) }) export default connect(mapStateToProps, mapDispatchToProps)(Counter) 此时还没有达到简化的效果,可以将 actionCreators 提取到单独的文件中。
// src\store\actions\counter.action.js export const increment = () => ({ type: 'increment' }) export const decrement = () => ({ type: 'decrement' })// src/components/Counter.js import { connect } from 'react-redux' import { bindActionCreators } from 'redux' import * as counterActions from '../store/actions/counter.action' function Counter({count, increment, decrement}) { return {count} } const mapStateToProps = state => ({ count: state.count }) const mapDispatchToProps = dispatch => bindActionCreators(counterActions, dispatch) export default connect(mapStateToProps, mapDispatchToProps)(Counter) 代码重构
为了继续演示 Redux 的相关内容,将与 Redux 相关的代码从 src/index.js中抽离出去,让项目结构更加合理。
- 将 reducer 函数抽离到一个文件中
- 将创建 store 的代码手里到一个文件中
- 将 Actions 的 type 抽象成模块中的成员,好处是:
编辑器有提示,避免写错
编辑器自动插入模块引入的代码
将 Actions 的 type 抽象成模块中的成员
// src\store\actions\counter.action.js import { DECREMENT, INCREMENT } from "../const/counter.const" export const increment = () => ({ type: INCREMENT }) export const decrement = () => ({ type: DECREMENT })将 reducer 函数抽离到一个文件中
// src\store\reducers\counter.reducer.js import { DECREMENT, INCREMENT } from "../const/counter.const" const initialState = { count: 0 } function reducer(state = initialState, action) { switch (action.type) { case INCREMENT: return { count: state.count + 1 } case DECREMENT: return { count: state.count - 1 } default: return state } } export default reducer 将创建 store 的代码手里到一个文件中
// src\store\index.js import { createStore } from 'redux' import reducer from './reducers/counter.reducer' export const store = createStore(reducer)修改后的 src/index.js
本站声明:
1、本站所有资源均来源于互联网,不保证100%完整、不提供任何技术支持;
2、本站所发布的文章以及附件仅限用于学习和研究目的;不得将用于商业或者非法用途;否则由此产生的法律后果,本站概不负责!
相关内容
- vue下载文件以及文件重命名方式_vue.js_
- vue遍历中存在el-form之踩坑记录_vue.js_
- Vue支持搜索与筛选的用户列表实现流程介绍_vue.js_
- Vue中的路由配置项meta使用解析_vue.js_
- vue中将el-switch值true、false改为number类型的1和0_vue.js_
- 微信小程序实现tab组件切换动画_javascript技巧_
- React中setState使用原理解析_React_
- 微信小程序网络数据请求服务实现详解_javascript技巧_
- 使用Vue-router二级路由跳转另一条路由下的子级_vue.js_
- 如何使用Gitee Pages服务 搭建Vue项目_vue.js_
点击排行
本栏推荐
