0%

React项目接入Redux

本篇文章不会对Redux的基础知识做过多的介绍, 仅仅讲解如何在 React 项目中, 接入 Redux 的功能

Redux与vue中的vuex类似, 主要作用是管理我们项目的全局状态数据的, 可以实现某些数据在所有组件中进行共享

一般来说, 除非你的组件很多, 页面很多, 处理各个组件之间的数据传递已经到了比较复杂的程度, 否则我们都不太建议使用 Redux 或 Vuex 之类的状态管理器

准备

如果我们要在 React 中使用 Redux , 那么我们需要安装几个第三方包, 在你的项目根目录下打开命令行, 执行以下命令:

yarn add redux react-redux

其中, redux 是实现我们全局状态管理的关键, 而 react-redux 则是起到了一个辅助的作用, 让我们在 React 中使用 Redux 更加容易些


创建目录

我演示的项目是用 create-react-app 进行创建的, 那么, 接下来, 我们需要在 src 这个目录下, 新添加一个目录, 名字就叫做 redux, 当然, 你想起别的名字也可以

此时, 我们的目录是下面这个样子的

node_modules
public
src
- redux
- App.js
- index.js
package.json

redux 文件夹下新建以下文件夹及文件:

  • reducers
    • musics.js
    • singers.js
  • actions
    • musics.js
    • singers.js
  • actionKey.js
  • store.js

此时你的 redux 目录下应该是这个样子的

redux // redux文件夹
- reducers // 存放所有的 reducers
- musics.js // 歌曲相关
- singers.js // 歌手相关
- index.js // 合并所有的reducer
- actions // 存放所有的actions
- musics.js // 歌曲相关
- singers.js // 歌手相关
- actionKey.js // action的key映射
- store.js // 核心store文件

代码配置

actionKey.js

我们先来配置 action的 key 映射文件, 当然, 你也可以不配这个东西, 它的作用是 记录所有 action 的 type

我们填入以下内容:

// actionKey.js
export const MUSICS = 'music';
export const SINGER = 'singer';

actions

接下来要配置我们的 actions 文件夹的内容, 这里 存放我们redux中用到的所有 actions

musics.js

这里配置所有歌曲的 actions

// actions/musics.js
import { MUSICS } from '../actionKey'
// 这是添加歌曲的action
export const appendMusic = data => ({ type: MUSICS, data });
singers.js

这里配置所有歌手的 actions

// actions/singers.js
import { SINGER } from '../actionKey'
// 这是添加歌手的action
export const appendSinger = data => ({ type: SINGER, data });

reducers

接下来要配置我们的 reducers 文件夹的内容, 这里 存放我们redux中用到的所有 reducers

musics.js

这里配置所有歌曲相关的 reducers

// reducers/musics.js
// 导入Action 的 Key
import { MUSICS } from '../actionKey'
// 初始数据
const initMusic = [
{ id: 1, musicName: '寻' }
]

// 处理Music的 Reducers
const musicReducers = (state = initMusic, action) => {
// 从action中取出 type 和 传递过来的 data
let { type, data } = action;
// 根据不同的 type 做出不同的操作
switch (type) {
case MUSICS:
// 如果 type === music, 则将代表添加一首歌, 我们则需要把 data 添加至数据前面
return [data, ...state];
default:
// 默认返回 state
return state;
}
}

export default musicReducers
singers.js

这里配置所有歌手相关的 reducers, 这里我就不写什么逻辑处理了, 因为这只是用来做演示的

// reducers/singers.js
const initSingers = [
{ id: 1, singerName: '刘增瞳' }
]
// 处理Singer的 Reducers
const singersReducers = (state = initSingers, action) => {
let { type, data } = action;
return state;
}

export default singersReducers
index.js

我们已经有musics.js和singers.js这2个reducers文件了, 接下来我们要做的是, 把这2个文件进行一个合并, 然后统一导出

之所以要统一合并, 是因为我们的 reducers 可能会有很多个, 就像我们有歌曲和歌手两个, 而 Redux 的 store 只有一个, 只能存一个, 所以呢, 我们要把它们合并为一个, 这样就能交给 store 进行统一管理了

// redux/reducers/index.js
import { combineReducers } from 'redux'
import musicsReduces from './musics'
import singersReduces from './singers'

export default combineReducers({
musicsReduces,
singersReduces,
})

合并多个 reducers 需要使用 combineReducers 这个方法来帮助我们, 而这个方法可以从 redux 中进行导入


store.js

当我们把之前的所有文件都配置好后, 我们就可以来写redux的核心实现了, 也就是我们的 store.js

import { createStore } from 'redux'
// 导入我们的reducers/index.js
import reducers from './reduces'
// 创建并导出我们的状态管理器
export default createStore(reducers)

createStore的第一个参数是 reducers, 第二个参数是第三方redux中间件


改造入口文件

接下来, 我们需要去修改我们的入口文件 src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// 导入Provider组件
import { Provider } from 'react-redux'
// 导入我们的状态管理器store
import store from './redux/store';

ReactDOM.render(
/* 把我们的状态管理器交给Provider */
<Provider store={store}>
<App />
</Provider>
,
document.getElementById('app')
);

Provider是 react-redux 所提供的组件, 它的作用是能够把我们的store提供给其下面的所有组件

也就是说, 当我们用 Provider 包裹住 App 组件后, 那么, App及其下面的所有组件, 都能够访问得到这个 store


使用redux

当我们上面的工作都做完之后, 我们就可以随便去写个页面, 进行一个测试了

例如我这里创建了一个 Home.jsx, 内容如下

import React from 'react';
// connect 的作用是将组件与store进行连接
import { connect } from 'react-redux';
// 导入我们添加音乐的actions
import { appendMusic } from '../../redux/actions/musics';

function Home(props) {
// input输入框元素
let input = null;

// 点击添加时, 往 state.musicsReduces 中添加一条新的数据
function handleClick() {
let value = input.value;
let musicObj = { id: Date.now(), musicName: value };
// 调用我们的action (react-redux会自动帮我们调用dispatch)
props.appendMusic(musicObj);
}

return (
<div>
<div>
<input type='text' ref={(el) => (input = el)} />
<button onClick={() => handleClick()}>添加</button>
</div>
<ul>
{props.musics.map((music) => {
return <li key={music.id}>{music.musicName}</li>;
})}
</ul>
</div>
);
}

// ---------------------- 以下是核心

// 将state里的musicsReduces取出, 并返回一个新对象, 这个新对象在后面会被合并到组件的 props 中
const mapStateToProps = (state) => ({ musics: state.musicsReduces });

// 将我们添加音乐的 action 添加到这个对象中,同样的, 它后面也会被合并到组件的 props中
const mapDispatchToProps = {
appendMusic, // 我们在上面导入的添加音乐action
};

// 使用connect,将我们的Home组件和store进行连接, 然后将我们配置好的 state 和 action 添加到组件的 props中
export default connect(mapStateToProps, mapDispatchToProps)(Home);

connect( 参数1, 参数2 ) (参数3)

  • 参数1:function(state): Object,作用是选择将store中的某些state添加到组件的props
  • 参数2:function(dispatch): Object | Object , 可以是一个函数, 也可以是一个对象, 选择将哪些方法添加至组件的props中
  • 参数3:ReactComponent, 一个组件, 作用是将我们前面配置好的参数1和参数2作用到哪个组件身上

如果参数1和参数2是可选的, 如果不想写,可以使用空对象 {} 进行替代

自此, 我们的效果就完成了, 我们就完成了 Redux 的接入


总结

当我们配置好redux之后, 如果需要在某个页面中使用, 则需要按照以下结构进行改造

// 导入连接组件和store的方法
import { connect } from 'react-redux';
// 导入actions
import { action1 } from '../../redux/actions/xxx';

// 你的组件
const TestComponent = (props) => {
console.log('props', props);
return <h1>这是测试组件</h1>
}

//-------------------------------------------

// 将state中的某些属性添加到props中,返回的必须是一个对象
const mapStateToProps = state => state;

// 将某个action添加到props中(对象写法)
const mapDispatchToProps1 = { action1 };

// 将某个action添加到props中(函数写法)
const mapDispatchToProps2 = dispatch => ({
method1(data) {
dispatch({type: 'xxx', data});
}
});

// 用connect对我们的组件进行处理并导出
export default connect(mapStateToProps, mapDispatchToProps1)(TestComponent);

一定要注意, connect 的第二个参数有对象写法和函数写法

如果你是对象写法, 那么 react-redux 会自动给你调用 dispatch方法

如果你是函数写法, 那么你就需要手动调用dispatch才能触发actions

大体框架就是这个样子, 你哪个页面需要用redux里的数据,那么你就得给哪个组件改造成这个样子


拓展

有兴趣可以去参考下 DvaJS

-------------本文结束    感谢阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!