项目结构
优化说明
1)容器组件和UI组件混合成一个文件
2)无需自己给容器传递store,在index.js入口文件给包裹一个Provider
<Provider store= {store}>
<App/>
</Provider>
3)使用了react-redux后也不用自己在index.js入口文件检测redux中状态的改变了,容器组件可以
自动完成
4).mapDispatchToProps也可以简单写成一个对象
5)一个组件要和redux打交道需要经过那几步?
A、定义好一个UI组件,不暴露
B、引入connect生成一个容器组件,并暴露,写法如下:
connect( state => ({key:value}) // 映射状态
{key:xxxxxAction} // 映射操作状态的方法
)(UI组件)
C、在UI组件中可以通过this.props.xxxx读取和操作状态
代码展示
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App.jsx'
import store from './redux/store'//为provider服务
import {Provider} from 'react-redux'
ReactDOM.render(
<Provider store= {store}>
<App/>
</Provider>,
document.getElementById('root')
)
// 检测redeux中状态的改变,若redux的状态发生了改变,那么重新渲染App组件
//使用react-redux创建容器组件后,react-redux可以自己实现检测state中状态的改变,所以可以删除
//以下代码
// store.subscribe(() => {
// ReactDOM.render(<App/>,document.getElementById('root'))
// })
App.jsx
import React, { Component } from 'react'
import Count from './containers/Count'
export default class App extends Component {
render() {
return (
<div>
<Count/>
</div>
)
}
}
container-count-index.jsx
//引入CountUI组件
// import CountUI from '../../compoents/Count'
import React, { Component } from 'react'
//引入connect用于连接UI组件和redux
import {connect} from 'react-redux'
//引入action
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
//定义UI组件
class Count extends Component {
state = {carName:'奔驰c63'}// 把状态交给reducer之后组件也可以有自己独用的状态
increment = () => {
const {value} = this.selectNum
this.props.jia(value*1)
}
decrement = () => {
const {value} = this.selectNum
this.props.jian(value*1)
}
incrementOdd = () => {
const {value} = this.selectNum
if(this.props.count % 2 !== 0) {
this.props.jia(value*1)
}
}
incrementWait = () => {
const {value} = this.selectNum
this.props.jiaAsync(value*1,400)
}
render() {
console.log('UI组件接收到的props是:',this.props);
return (
<div>
<h1>当前求和为:{this.props.count}</h1>
<select ref={c => {this.selectNum = 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.incrementOdd}>当前求和为奇数再加</button>
<button onClick= {this.incrementWait}>等一等再加</button>
</div>
)
}
}
//使用connect()()创建并暴露一个Count容器组件
export default connect(
state => ( {count:state}),
//mapDispatchToProps的一般写法
// dispatch => ({
// jia:number => dispatch(createIncrementAction(number)),
// jian:number => dispatch(createDecrementAction(number)),
// jiaAsync:(number,time) =>dispatch(createIncrementAsyncAction(number,time))
// })
//mapDispatchToProps的简写,dispatch由react-redux来完成,程序员工作中用这种方法
{
jia:createIncrementAction,
jian:createDecrementAction,
jiaAsync:createIncrementAsyncAction
}
)(Count)
redux-store.js
/*
该文件专门用于暴露一个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'
export default createStore(countReducer, applyMiddleware(thunk))
redux-count_reducer.js
/*
1.该文件用于创建一个为count组件服务的reducer,reducer的本质就是一个函数
2.reducer函数会接到两个参数,分别是之前的state(状态)和action(动作对象)
*/
import { INCREMENT, DECREMENT } from "./constant";
const initState = 0
export default function countReducer(preState=initState, action) {
// console.log(preState, action);
//从action对象中获取type, data
const {type, data} = action
//根据type类型决定如何加工
switch (type) {
case INCREMENT:// 如果是加
return preState + data
case DECREMENT:// 如果是减
return preState - data
default:
return preState
}
}
redux-count_actions.js
/*
该文件专门为count组件生成action对象
*/
import { INCREMENT, DECREMENT } from "./constant"
//完整写法
// function createIncrementAction(data) {
// return {type:'increment', data }
// }
//简写形式
export const createIncrementAction = data =>( {type:INCREMENT, data })
//完整写法
// function createDecrementAction(data) {
// return {type:'decrement', data}
// }
export const createDecrementAction = data =>( {type: DECREMENT, data })
//异步action,就是值action的返回值是函数,异步action一般都会调用同步action
//异步action不是必须要用的
export const createIncrementAsyncAction = (data, time) =>{
return (dispatch) => {
setTimeout(() => {
dispatch(createIncrementAction(data))
},time)
}
}
redux-constant.js
/*
该文件是用于定义action对象中的type类型的常量值
目的只有一个:防止程序员在编码的同时单次写错
*/
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'