安装react-redux
tnpm i react-redux
未优化前:
—— src/components/Count/index.tsx
import React, { useState } from 'react'
export default function CountUI(props:any) {
console.log('UI组件接收到的props是', props)
const [value, setValue] = useState<number>(0)
const increment = () => {
props.incre(value * 1)
}
const decrement = () => {
props.decre(value * 1)
}
const incrementIfOdd = () => {
if (props.count % 2 !== 0)
props.incre(value * 1)
}
const incrementAsync = () => {
props.increAsync(value * 1, 1000)
}
const select = (e: any) => {
const index = e.target.selectedIndex // 选中项的index
setValue(e.target.options[index].value) // 选中项的value值
}
return (
<div>
<h1>当前求和为: {props.count}</h1>
<select onChange={select}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={incrementAsync}>异步加</button>
</div>
)
}
—— src/containers/Count/index.tsx
// 引入Count的UI组件
import CountUI from '../../components/Count'
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
// 引入connect用于连接UI组件与redux
import { connect } from 'react-redux'
// mapStateoProps函数返回的对象中的key作为传递给UI组件props的key
// value作为传递给UI组件props的value
// —— mapStateoProps用于传递状态
function mapStateoProps(state: any) {
return {count: state}
}
// mapDispatchToProps函数返回的对象中的key作为传递给UI组件props的key
// value作为传递给UI组件props的value
// ——mapDispatchToProps用于创建操作状态的方法
function mapDispatchToProps(dispatch: any) {
return {
incre: (data: number) => {
dispatch(createIncrementAction(data))
},
decre: (data: number) => {
dispatch(createDecrementAction(data))
},
increAsync: (data: number, time: number) => {
dispatch(createIncrementAsyncAction(data, time))
}
}
}
—— src/pages/index.css
import styles from './index.less';
import Count from '../containers/Count'
import store from '../redux/store'
export default function IndexPage() {
return (
<div>
<Count store={store}/>
</div>
);
}
—— src/redux/contant.ts
/*
该模块用于定义action对象中type类型的常量值,
目的:便于管理的同时,防止程序员单词写错
变量写错的话,会报错
*/
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
—— src/redux/count_action.ts
/*
该文件专门为Count组件生成action对象
*/
import { INCREMENT, DECREMENT } from './contant'
import store from './store'
// 同步action:action的值是Object类型的一般对象
export const createIncrementAction = (data: number) => (
{type: INCREMENT, data}
)
export const createDecrementAction = (data: number) => (
{type: DECREMENT, data}
)
// 异步action:action的值为函数;
// 异步action中一般都会调用同步action,异步action不是必须要调用的
export const createIncrementAsyncAction = (data: number, time:number) => {
return () => {
setTimeout(() => {
// store.dispatch({type: INCREMENT, data})
// 两种方法都可以,最好选择下面的写法
store.dispatch(createIncrementAction(data))
}, time)
}
}
—— src/redux/count_reducer.ts
/*
该文件用于创建一个为Count组件服务的reducer,reducer的本质是一个函数
reducer函数接收两个参数:之前的状态preState,动作对象action
*/
import { INCREMENT, DECREMENT } from './contant'
// 初始化时,preState为undefined
const initState = 0
export default function countReducer (preState=initState, action: any) {
// 从action对象中获取type和data
const { type, data } = action
switch(type) {
case INCREMENT:
return preState + data
case DECREMENT:
return preState - data
default:
return preState
}
}
—— src/redux/store.ts
/*
该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/
// 引入createStore,专门用于创建redux中最为核心的store对象
import { createStore, applyMiddleware } from 'redux'
// 引入为Count组件服务的reducer
import CountReducer from './count_reducer'
// 引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'
// 暴露store
export default createStore(CountReducer, applyMiddleware(thunk))
优化后:
—— mapDispatchToProps也可以是一个对象
—— store状态发生变化后,不再需要重新渲染
不需要再写subscribe
—— provider
如果组件中有很多容器组件,每一次都需要写store={store}
<Count store={store}/>
<Demo store={store}/>
<Demo1 store={store}/>
现在可以这样解决:
在入口文件中:
import React from 'react'
import ReactDom from 'react-dom'
import App from './App'
import store from './redux/store'
import { provider } from 'react-redux'
ReactDom.render(
<Provider store={store}>
<App/>
<Provider>,
document.getElementById('root')
)
—— 整合UI组件和容器组件
—— 优化的总结
—— 代码:
import React, { useState } from 'react'
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
// 引入connect用于连接UI组件与redux
import { connect } from 'react-redux'
function CountUI(props:any) {
console.log('UI组件接收到的props是', props)
const [value, setValue] = useState<number>(0)
const increment = () => { props.incre(value * 1) }
const decrement = () => { props.decre(value * 1) }
const select = (e: any) => {
const index = e.target.selectedIndex // 选中项的index
setValue(e.target.options[index].value) // 选中项的value值
}
return (
<div>
<h1>当前求和为: {props.count}</h1>
<select onChange={select}>
<option value="1">1</option>
<option value="2">2</option>
</select>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
)
}
// 映射状态
const mapStateoProps = (state: any) => ({count: state})
// 映射操作状态的方法
const mapDispatchToProps = {
incre: createIncrementAction,
decre: createDecrementAction,
increAsync: createIncrementAsyncAction
}
export default connect(mapStateoProps, mapDispatchToProps)(CountUI)
import styles from './index.less';
import store from '../redux/store'
import OptimizeCount from '../containers/OptimizeCount'
export default function IndexPage() {
return (
<div>
<OptimizeCount store={ store }/>
</div>
);
}