我是靠谱客的博主 清新绿草,这篇文章主要介绍react-redux 简单封装react-redux 简单封装,现在分享给大家,希望可以做个参考。

react-redux 简单封装

安装

复制代码
1
2
3
4
npm install --save redux npm install --save react-redux npm install --save-dev redux-devtools

依照官方实例 Todo List

处理 reducers

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 官方例子 const todos = (state = [], action) => { switch (action.type) { case 'ADD_TODO': return [ ...state, { id: action.id, text: action.text, completed: false } ] case 'TOGGLE_TODO': return state.map(todo => (todo.id === action.id) ? {...todo, completed: !todo.completed} : todo ) default: return state } } export default todos
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 处理完的 todos.ts // store/reducers/todos.ts // 使用对象进行匹配,可将 actions 直接去掉 export interface TodoItem { id: number text: string completed: boolean } export type TodoStateProps = TodoItem[] let nextTodoId = 0 const mutations: { [key: string]: (state: TodoStateProps, payload: unknown) => TodoStateProps } = { 'ADD_TODO': (state: TodoStateProps, payload: unknown): TodoStateProps => { const action = payload as TodoItem return [ ...state, { id: nextTodoId++, text: action.text, completed: false } ] }, 'TOGGLE_TODO': (state: TodoStateProps, payload: unknown): TodoStateProps => { const action = payload as TodoItem return state.map(todo => (todo.id === action.id) ? { ...todo, completed: !todo.completed } : todo ) } } const todos = (state: TodoStateProps = [], action: { type: string }): TodoStateProps => { const { type, ...payload } = action if (mutations[type]) { return mutations[type](state, payload) } else { return state } } export default todos
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 调用方式 import React from 'react' import { connect, DispatchProp } from 'react-redux' let AddTodo = ({ dispatch }: DispatchProp<any>) => { let input: HTMLInputElement | null return ( <div> <form onSubmit={e => { e.preventDefault() if (input) { if (!input.value.trim()) { return } const timer = setTimeout(() => { if (input) { clearTimeout(timer) dispatch({ type: 'ADD_TODO', text: input.value }) // 直接传入一个 action 对象即可 input.value = '' } }, 1000) } }} > <input ref={node => { input = node }} /> <button type="submit"> Add Todo </button> </form> </div> ) } export default connect()(AddTodo)

处理 component

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// utils/index.ts // 组件处理函数 import { PropsWithChildren } from 'react' import { connect, Matching } from 'react-redux' import { AnyAction } from 'redux' import { stateProps, actions } from '../store/reducers' // 执行异步的 reducers const handleDispatchAction = async (dispatch: any) => { return (action: AnyAction) => { const { type, ...payload } = action if (actions[type]) { await actions[type](dispatch, payload) } else { throw new Error(`${type} 没找到对应的 action`) } } } // 规定类型 export type dispatchActionType = (action: AnyAction) => void type PropsType<T> = PropsWithChildren<Matching<{ storeState: stateProps; ownProps: T; } & { dispatch: any; dispatchAction: dispatchActionType; }, T>> // 使用泛型来规定 props 参数 export const componentConnect = <T> (component: (props: PropsType<T>) => JSX.Element) => { // 将 state, dispatch, dispatchAction 通过函数参数的方式注入到函数内 const mapStateToProps = (state: stateProps, ownProps: Omit<T, 'storeState' | 'dispatch' | 'dispatchAction'>) => { return { storeState: state, ownProps } } const mapDispatchToProps = async (dispatch: any) => { return { dispatch, dispatchAction: await handleDispatchAction(dispatch) } } const connectComponent = connect( mapStateToProps, mapDispatchToProps )(component) return connectComponent }
以 Link.js 为例
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 官方 // 通过组件加容器的方式进行处理 // components/Link.js import React from 'react' import PropTypes from 'prop-types' const Link = ({ active, children, onClick }) => { if (active) { return <span>{children}</span> } return ( <a href="" onClick={e => { e.preventDefault() onClick() }} > {children} </a> ) } Link.propTypes = { active: PropTypes.bool.isRequired, children: PropTypes.node.isRequired, onClick: PropTypes.func.isRequired } export default Link
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 官方 // containers/FilterLink.js import { connect } from 'react-redux' import { setVisibilityFilter } from '../actions' import Link from '../components/Link' const mapStateToProps = (state, ownProps) => { return { active: ownProps.filter === state.visibilityFilter } } const mapDispatchToProps = (dispatch, ownProps) => { return { onClick: () => { dispatch(setVisibilityFilter(ownProps.filter)) } } } const FilterLink = connect( mapStateToProps, mapDispatchToProps )(Link) export default FilterLink
经过处理后的
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { MouseEventHandler, ReactNode } from 'react' import { componentConnect } from '../utils' import { stateProps } from '../store/reducers' interface LinkProps { children: ReactNode, filter: string, storeState: stateProps, dispatch: any } const Link = ({ storeState, children, dispatch, ...ownProps }: LinkProps) => { if (storeState?.visibilityFilter === ownProps.filter) { return <span>{children}</span> } const handleClick: MouseEventHandler<HTMLButtonElement> = (e) => { e.preventDefault() dispatch({ type: 'SET_VISIBILITY_FILTER', filter: ownProps.filter }) } return ( <> <button onClick={handleClick}> {children} </button> </> ) } export default componentConnect<LinkProps>(Link) // 通过泛型传入 props 参数, 可在组件直接使用

处理异步的 reducers

以 visibilityFilter.js 为例

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
export type visibilityFilterStateProps = string const mutations: { [key: string]: (state: visibilityFilterStateProps, payload: unknown) => visibilityFilterStateProps } = { 'SET_VISIBILITY_FILTER': (state, payload) => { const action = payload as { filter: string } return action.filter } } // 添加一个处理异步的 actions export const actions = { 'SYNC_SET_VISIBILITY_FILTER': async (dispatch: any, payload: unknown) => { const params = payload as Object await new Promise<void>((resolve, reject) => { const timer = setTimeout(() => { clearTimeout(timer) dispatch({ type: 'SET_VISIBILITY_FILTER', ...params }) resolve() }, 1000) }) } } const visibilityFilter = (state: visibilityFilterStateProps = 'SHOW_ALL', action: { type: string, payload: unknown }): visibilityFilterStateProps => { const { type, ...payload } = action if (mutations[type]) { return mutations[type](state, payload) } else { return state } } export default visibilityFilter
核心处理部分
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 在 store/reducers/index.ts 中 // 使用 webpack 的 require.context 载入各个 reducers // ts 环境记得添加 webpack 类型 npm i @types/webpack-env @types/node -D const modules = require.context('.', false, /^./(?!index)w+.ts$/) // 组合,导出 reducers 的 actions export const actions = modules.keys().reduce((pre: { [key: string]: (dispatch: any, ...params: any) => void }, key: string) => { return Object.assign(pre, modules(key).action || {}) }, {}) // 在 utils/index.ts 中 // 导入 actions import { stateProps, actions } from '../store/reducers' // 执行异步的 reducers const handleDispatchAction = async (dispatch: any) => { return (action: AnyAction) => { const { type, ...payload } = action if (actions[type]) { await actions[type](dispatch, payload) } else { throw new Error(`${type} 没找到对应的 action`) } } } const mapDispatchToProps = async (dispatch: any) => { return { dispatch, dispatchAction: await handleDispatchAction(dispatch) // 将 dispatchAction 一起注入到函数内 } }
使用
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { MouseEventHandler, ReactNode } from 'react' import { componentConnect, dispatchActionType } from '../utils' import { stateProps } from '../store/reducers' interface LinkProps { children: ReactNode, filter: string, storeState: stateProps, dispatch: any, dispatchAction: dispatchActionType } const Link = ({ storeState, children, dispatch, dispatchAction, ...ownProps }: LinkProps) => { if (storeState?.visibilityFilter === ownProps.filter) { return <span>{children}</span> } const handleClick: MouseEventHandler<HTMLButtonElement> = async (e) => { e.preventDefault() await dispatchAction({ type: 'SYNC_SET_VISIBILITY_FILTER', filter: ownProps.filter }) // 使用 dispatchAction 进行调用 // dispatch({ type: 'SET_VISIBILITY_FILTER', filter: ownProps.filter }) } return ( <> <button onClick={handleClick}> {children} </button> </> ) } export default componentConnect<LinkProps>(Link)

最后

以上就是清新绿草最近收集整理的关于react-redux 简单封装react-redux 简单封装的全部内容,更多相关react-redux内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(102)

评论列表共有 0 条评论

立即
投稿
返回
顶部