redux一直有研究,不过没有在项目中具体用过,今天提到了一个需求,我立马就想到了用redux。
需求
- 多个组件外部可以单独添加到类似“购物车”之类的,然后最外部有个炫富的图标记录选中的个数,并且点击能看到明细。
类似于下图(单词旁边还可能有,课文,句子等),所以组件很多。(下面的每一个tab都是一个组件,因为内部显示不一致)
image.png
技术实现
- 先不说原理,先实现需求,技术原理以及优化慢慢在叙。
redux,几要素:
- store, reducer, action,
安装两个npm包
npm install redux --save
npm install react-redux --save
store 创建方法
import reducer from './reducer' ;
import { createStore } from 'redux' ;
const store = createStore(reducer) ;
reducer 创建方法
export default (state = defaultState, action) => {
// 这里做action type 判断
switch (action.type) {
case ADD_CART:
return {
...state,
};
case 'MIN_CART':
return {
...state,
}
default:
return state;
}
};
action 创建
export function addTodo(text) {
return { type: 'ADD_TODO', text }
}
export function toggleTodo(index) {
return { type: 'TOGGLE_TODO', index }
}
项目结构以及代码
store文件夹下的结构
image.png
最外层组件 index.js
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './store/reducer';
import Content from './NewChapter';
const QuestionChapter = props => {
const { match } = props;
const { bookId, chapterId } = match.params;
const store = createStore(rootReducer);
return (
<Provider store={store}>
<Content bookId={bookId} chapterId={chapterId} />
</Provider>
);
};
export default QuestionChapter;
NewChapter.js
import React, { PureComponent } from 'react';
import { connect as reduxConnect } from 'react-redux';
import { minFromCart } from './store/actions';
import Speaking from './Speaking';
class QuestionChapter extends Purecomponent(){
render(){
const {currentBookId, currentActiveTabKey, currentItemChapterId = 0 } = this.state;
// 每次点击事件加减时候会产生这里的textArr的变化,从而更新购物车中的数目
const { textArr } = this.props;
return (
<div>
<ReadingContent
bookId={currentBookId}
bookChapterId={currentItemChapterId}
currentActiveTabKey={currentActiveTabKey}
/>
</div>
}
const mapStateToProps = state => {
return {
textArr: state.textArr,
};
};
const mapDispatchToProps = dispatch => {
return {
minTextBook: id => dispatch(minFromCart(id)),
};
};
export default reduxConnect(mapStateToProps, mapDispatchToProps)(QuestionChapter);
Speaking.js
import React, { PureComponent, Fragment } from 'react';
import { addToCart } from '../../store/actions';
import { connect as reduxConnect } from 'react-redux';
class WordPureComponent extends PureComponent {
// 某个按钮的点击事件
handleClickIntoText = val => {
const { addToCart: propsAddCart } = this.props;
propsAddCart(val);
};
render(){
return <div>111</div>
}
}
const mapStateToProps = () => ({});
const mapDispatchToProps = dispatch => ({
addToCart: value => dispatch(addToCart({ ...value })),
});
export default reduxConnect(mapStateToProps, mapDispatchToProps)(WordPureComponent);
store 文件夹下
index.js
import { creatStore } from 'redux';
import reducer from './reducer';
const store = creatStore(reducer);
export default store;
action.js
import { ADD_CART, MIN_CART } from './constant';
export const addToCart = payload => ({
type: ADD_CART,
payload: {
id: 1,
...payload,
},
});
export const minFromCart = id => ({
type: MIN_CART,
payload: {
id,
},
});
contant.js
export const ADD_CART = 'ADD_CART';
export const MIN_CART = 'MIN_CART';
reducer.js
import { ADD_CART } from './constant';
import { handleConcatTwoArrToUniqueArr } from '../../../assets/common/common';
const defaultState = {
textArr: [],
};
export default (state = defaultState, action) => {
const { payload = {} } = action;
const newArr = [];
newArr.push(payload);
// 这里做action type 判断
switch (action.type) {
case ADD_CART:
return {
...state,
textArr: handleConcatTwoArrToUniqueArr(newArr, state.textArr, 'id'),
};
case 'MIN_CART':
return {
...state,
textArr: state.textArr.filter(item => item.id !== payload.id),
};
default:
return state;
}
};
网友评论