react-redux
yarn add redux
yarn add react-redux
开发者工具:yarn add redux-devtools-extension
-
两个概念:
-
UI组件不能使用任何redux的api,只负责页面呈现和交互等
-
容器组件,负责和redux通信,将结果交给UI组件
- 如何创建容器组件————靠react-redux的connect函数
- connect(mapStateToProps,mapDispatchToProps)(UI组件)
- mapStateToProps:映射状态,返回值是一个对象
- mapDispatchToProps:映射操作状态的方法,返回值是一个对象
- 如何创建容器组件————靠react-redux的connect函数
-
-
备注:容器组件中的store是靠props传进去的,不是在容器组件中直接引入
-
和redux区别:多一层容器组件,删除原来UI组件关于redux的方法
容器组件:
import CountUI from '../../components/Count'
import {createIncrementAction,createDecrementAction,createIncrementAsyncAction} from '../../redux/count_action'
// 引入store,别自己引入,靠父组件传
// import store from '../../redux/store'
//引入connect,使用connect创建并暴露一个Count容器组件
import {connect} from 'react-redux'
//a函数的返回的对象作为状态传递给了UI组件
//第一个参数为函数(1)redux中所保存的状态
function mapStateToProps(state){
return {count:state}
}
// (1)用于操作状态的方法
function mapDispatchToProps(dispatch) {
return {
// 通知redux执行加法
jia:number=>dispatch(createIncrementAction(number)),
// 通知redux执行减法
jian:number=>dispatch(createDecrementAction(number)),
jiaAsync:(number,time)=>dispatch(createIncrementAsyncAction(number,time)),
}
}
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)//connect返回值也是一个函数,然后调用
UI组件:
import React, { Component } from 'react'
//为了获取状态
export default class Count extends Component {
state={carname:'奔驰c63'}
increment = () => {
const { value } = this.selectNumber;
this.props.jia(value*1)
}
decrement = () => {
const { value } = this.selectNumber;
this.props.jian(value*1)
}
incrementIfOdd = () => {
const { value } = this.selectNumber;
if(this.props.count%2!==0){
this.props.jia(value*1)
}
}
incrementAsync = () => {
const { value } = this.selectNumber;
this.props.jiaAsync(value*1,500)
}
render() {
//ui组件接收到的props
// console.log(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.decrement}>-</button>
<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
)
}
}
容器组件简写:react-redux底层做dispatch处理,传mapDispatchToProps对象
import CountUI from '../../components/Count'
import { createIncrementAction, createDecrementAction, createIncrementAsyncAction } from '../../redux/count_action'
import { connect } from 'react-redux'
// const mapStateToProps=state=> ({count: state })
// function mapDispatchToProps(dispatch) {
// return {
// jia: number => dispatch(createIncrementAction(number)),
// jian: number => dispatch(createDecrementAction(number)),
// jiaAsync: (number, time) => dispatch(createIncrementAsyncAction(number, time)),
// }
// }
export default connect(
state => ({ count: state }),
{
jia: createIncrementAction,
jian: createDecrementAction,
jiaAsync: createIncrementAsyncAction
}
)(CountUI)
index.js简化
1.
//不引入store
//store.subscribe注释
2.使用Provider的时候
import store from './redux/store'
import {Provider的时候} from 'react-redux'
ReactDOM.render(
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>,
document.getElementById('root')
);
容器组件和UI组件组成一个文件,container
手写一个container练习连接redux
import React, { Component } from 'react'
import { createIncrementAction } from '../../redux/count_action'
import { connect } from 'react-redux'
class Count extends Component {
add = () => {
this.props.jia(1)
}
render() {
return (
<div>
<button onClick={this.add}>点我加一</button>
<div>数值:{this.props.he}</div>
</div>
)
}
}
export default connect(
state => ({ he: state })
,
{
jia: createIncrementAction
}
)(Count)
多个reduces的时候,使用combineReducers
//store.js:
import {createStore,applyMiddleware,combineReducers} from 'redux'
import countReducer from './reducers/count.js'
import personReducer from './reducers/person.js'
//引入redux-thunk,可以dispatch函数
import thunk from 'redux-thunk'
// 总的reducer
const allReducer = combineReducers({
he:countReducer,
rens:personReducer
})
export default createStore(allReducer,applyMiddleware(thunk))
//Person.jsx组件:
import React, { Component } from 'react'
import {nanoid} from 'nanoid'
import {connect} from 'react-redux'
import {addCreateAction} from '../../redux/actions/person'
class Person extends Component {
addPerson = () => {
const name = this.nameNode.value;
const age = this.ageNode.value;
const personObj = {id:nanoid(),name,age}
this.props.add(personObj)
}
render() {
console.log(this.props)
return (
<div>
<hr />
<h2>我是person组件</h2>
<input ref={c=>this.nameNode=c} type="text" placeholder="输入名字"/>
<input ref={c=>this.ageNode=c} type="text" placeholder="输入年龄"/>
<button onClick={this.addPerson}>添加</button>
<ul>
{/* <li>{this.props.person.name}--年龄1</li> */}
{
this.props.person.map(ele=>{
return (
<li key={ele.id}>{ele.name}--{ele.age}</li>
)
})
}
<li>{this.props.count}</li>
</ul>
</div>
)
}
}
export default Person = connect(
// 因为是总状态
state=>({person:state.rens,
count:state.he})
,
{add:addCreateAction}
)(Person)
reducer.js中需要纯函数
- 同样的输入,必得到同样的输出(返回)
- 不得改写参数数据
- 不会产生副作用,如网络请求,输入输出设备
- 不能Data.now()或者Math.random()
redux开发者工具
-
yarn add redux-devtools-extension
-
store中配置
import {composeWithDevTools} from ‘redux-devtools-extension’
const store = creteStore(allReducer,composeWithDevTools(applyMiddleWare(thunk)))
把汇总reducers放在reducers文件夹暴露给store
// 汇总reducer,不要在store中引入
import {combineReducers} from 'redux'
import countReducer from './count.js'
import personReducer from './person.js'
export default combineReducers({
he:countReducer,
rens:personReducer
})
//store.js
import {createStore,applyMiddleware} from 'redux'
import allReducer from './reducers/index.js'
//引入redux-thunk,可以dispatch函数
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension'
export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))