redux、react-redux入门

327 阅读4分钟

redux、react-redux入门

redux

简单介绍一下redux,下面会详细使用它。

它和vuex作用相同,作为应用全局状态数据管理,完美结合react不可变值,纯函数的思想

单向数据流描述

dispatch(action)

reducer -> newState

subscribe 触发通知

react-redux

两个概念

  • UI组件:不能使用任何redux的api(dispatch...),只负责页面的呈现、交互等。
  • 容器组件:负责和redux通信,将结果返回给UI组件

两个核心

connect函数

如何创建一个容器组件?--- 靠react-reduxconnect高阶函数

connect( mapStateToProps, mapDispatchToProps )( UI组件 )

  • mapStateToProps: 映射状态,返回值是一个对象
    • mapStateToProps函数返回的是一个对象;
    • 返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
    • mapStateToProps用于传递状态
  • mapDispatchToProps: 映射操作状态的方法,返回值是一个对象
    • mapDispatchToProps函数返回的是一个对象;
    • 对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
    • mapDispatchToProps用于传递操作状态的方法

Provider组件

不使用provider需自己给容器组件传递store,如果组件过多的话......。

<Count store={store}></Count>
<Count1 store={store}></Count1>
<Count2 store={store}></Count2>
...

使用Provider组件则无需如此,给包裹一个即可实现store在所有组件中使用。

<Provider store={store}>
    <App/>
</Provider>

react-redux 选择添加案例

Count.jsx

// 此时点击事件仅仅是得到选择的值而已。
// 还没有引入react-redux
export default class Count extends Component {
	//加法
	increment = ()=>{
		const {value} = this.selectNumber
	}
	//奇数再加
	incrementIfOdd = ()=>{
		const {value} = this.selectNumber
	}
	//异步加
	incrementAsync = ()=>{
		const {value} = this.selectNumber
	}

	render() {
		// console.log('UI组件接收到的props是',this.props);
		return (
			<div>
				<h1>当前求和为:</h1>
				<select ref={c => this.selectNumber = c}>
					<option value="1">1</option>
					<option value="2">2</option>
					<option value="3">3</option>
				</select>&nbsp;
				<button onClick={this.increment}>+</button>&nbsp;
				<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>&nbsp;
				<button onClick={this.incrementAsync}>异步加</button>&nbsp;
			</div>
		)
	}
}

App.jsx

</div> <Count></Count> <div>

Index.js入口文件

ReactDOM.render(
	<App/>,
	document.getElementById('root')
)

到这里,都只是一些简单的代码。还没有使用react-redux噢,接下来就开始使用。

// 创建constant.js放置容易写错的type值
export const INCREMENT = 'INCREMENT'

store.js

/* 
	该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/

// 引入createStore,专门用于创建redux中最为核心的store对象
// applyMiddleware为redux应用
import {createStore,applyMiddleware} from 'redux'
// 引入为Count组件服务的reducer
import countReducer from './count_reducer'
// 引入redux-thunk,用于支持异步action
// 如果这里不使用redux-thunk,则下面的异步action不会生效
import thunk from 'redux-thunk'
//暴露store
export default createStore(countReducer,applyMiddleware(thunk))

count_reducer.js

  1. 该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
  2. reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
  3. 初始化state,为什么需要初始化state?当你传入undefined或者初始state是undefined的时候,会抛出异常。
import * as types from './constant'
// 初始化state 或者在reducer函数中手动检查第一个参数是否为undefined。
const initState = 0 
export default function countReducer(preState = initState,action){
	// console.log(preState);
	// 从action对象中获取:type、data
   	// 这个data和type对应下面的count_action.js的action
	const {type,data} = action
	//根据type决定如何加工数据
	switch (type) {
		case types.INCREMENT:
			return preState + data
		default:
			return preState
	}
}

count_action.js

  1. action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作
/* 
	该文件专门为Count组件生成action对象
*/
import * as types from './constant'

// 同步action,就是指action的值为Object类型的一般对象
// 注意:这里的 type 和 data 对应 reducer 中从 action 参数获取的 type 和 data
export const createIncrementAction = data => ({type:types.INCREMENT,data})

// 异步action,就是指action的值为函数,异步action中一般都会调用同步action,这里一般会发送axios请求后去调用同步action。
// 在上面store引入redux-thunk,用于支持异步action。
export const createIncrementAsyncAction = (data,time) => {
	return (dispatch)=>{
        // 发送请求..... 获取data
		setTimeout(()=>{
			dispatch(createIncrementAction(data))
		},time)
	}
}

最后,需要对Count组件使用connect函数。

class Count extends Component {
	//加法
	increment = ()=>{
		const {value} = this.selectNumber
        this.props.jian(value*1)
	}

    //异步加
	incrementAsync = ()=>{
		const {value} = this.selectNumber
		this.props.jiaAsync(value*1,500)
	}
    
	render() {
		// console.log('UI组件接收到的props是',this.props);
		return (
			<div>
				<h1>当前求和为:{this.props.count}</h1>
				<select ref={c => this.selectNumber = c}>
					<option value="1">1</option>
					<option value="2">2</option>
					<option value="3">3</option>
				</select>&nbsp;
				<button onClick={this.increment}>+</button>&nbsp;
				<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>&nbsp;
				<button onClick={this.incrementAsync}>异步加</button>&nbsp;
			</div>
		)
	}
}

// 箭头函数返回对象要用()
const mapStateToProps = state => ({count:state})

const mapDispatchToProps = dispatch =>(
    {
		jia:number => dispatch(createIncrementAction(number)),
		jiaAsync:(number,time) => dispatch(createIncrementAsyncAction(number,time)),
	}
)

// 使用connect()()创建并暴露一个Count的容器组件
export default connect(mapDispatchToProps,mapDispatchToProps)(Count)

别忘了,需要使用Provider组件包裹App并且传入store

import store from './redux/store'
import {Provider} from 'react-redux'

ReactDOM.render(
	<Provider store={store}>
		<App/>
	</Provider>,
	document.getElementById('root')
)

这样,就完成了这个添加的案例。

有错误的或者不足的地方请指出,谢谢观看。