redux、react-redux入门
redux
简单介绍一下redux,下面会详细使用它。
它和vuex作用相同,作为应用全局状态数据管理,完美结合react不可变值,纯函数的思想
单向数据流描述
dispatch(action)
reducer -> newState
subscribe 触发通知
react-redux
两个概念
- UI组件:不能使用任何redux的api(dispatch...),只负责页面的呈现、交互等。
- 容器组件:负责和redux通信,将结果返回给UI组件
两个核心
connect函数
如何创建一个容器组件?--- 靠react-redux的connect高阶函数
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>
<button onClick={this.increment}>+</button>
<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={this.incrementAsync}>异步加</button>
</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
- 该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
- reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
- 初始化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
- 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>
<button onClick={this.increment}>+</button>
<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={this.incrementAsync}>异步加</button>
</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')
)
这样,就完成了这个添加的案例。
有错误的或者不足的地方请指出,谢谢观看。