react学习记录-redux
文章目录
一、Ant Design 插件
1.修改主体颜色
1.安装依赖: npm add react-app-rewired customize-cra babel-plugin-import less less-loader
2.修改package.json
代码如下
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
3.根目录下创建config-overrides.js
文件代码如下:
jsconst { override, fixBabelImports, addLessLoader } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
lessOptions:{
javascriptEnabled: true,
modifyVars: {'@primary-color': 'orange'}
}
}),
);
二. redux
1.redux 是什么
1.redux是一个专门用于做状态管理的js库
2.作用: 集中管理react应用中多个组件共享的状态
2.redux的原理图
3. redux的API
A.求和案例-redux精简版
1.src下新建redux文件夹,store.js, reducer.js 文件
2.store.js
1) 引入redux中放入createStore函数,创建一个store
2) createStore调用时要传入一个为其服务的reducer
3) 暴露store对象
/*该文件专门用于暴露一个store 对象,整个应用只有一个store对象*/
import {createStore} from 'redux'
import countReducer from './count_reducer'
//暴露store
export default createStore(countReducer)
3.reducer.js
1) reducer的本质是一个函数,接收:prestate, action 返回加工后的状态
2) reducer有两个作用,初始化状态,加工状态
3) reducer被第一次调用时,是store自动触发的,传递的prestate是undefined
4.在index.js中检测store中状态的改变,一旦发生改变重新渲染.
const initState = 0 //初始化
export default function countReducer(preState=initState,action){
const {type,data} = action
switch(type){
case 'increment':
return preState + data
case 'decrement':
return preState - data
default:
return preState
}
}
B.求和案例-redux完整版
1.创建action.js: 该文件专门为组件生成action 对象
export const createIncrementAction = data => ({type:'increment',data})
export const createDecrementAction = data => ({type:'decrement',data})
2.创建store.js: 该文件专门用于暴露一个store 对象,整个应用只有一个store对象
import {createStore} from 'redux'
import countReducer from './count_reducer'
//暴露store
export default createStore(countReducer)
3.创建reducer:函数根据action 中的type做出不同的处理
const initState = 0 //初始化
export default function countReducer(preState=initState,action){
const {type,data} = action
switch(type){
case 'increment':
return preState + data
case 'decrement':
return preState - data
default:
return preState
}
}
4. 在组件中通过导入store,调用store.dispatch,使用action返回的对象,通知reducer做出数据处理,在index.js里通过store.subscribe渲染页面.
increament=()=>{
const {value} = this.selectNumber
// 通知redux加 createIncrementAction通过action导入
store.dispatch(createIncrementAction(value*1))
}
import store from "./redux/store";
store.subscribe(()=>{
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
})
C. redux异步action
1.安装依赖 npm add redux-thunk ,配置在store中
import {createStore,applyMiddleware} from 'redux'
import countReducer from './count_reducer'
import thunk from 'redux-thunk'
//暴露store
export default createStore(countReducer,applyMiddleware(thunk))
2.创建action的函数不在返回一个对象,而是返回一个函数,在函数中写异步任务
//同步action 指返回的值是对象类型
//异步action 就是指返回的值是函数 异步action 中一般都会开启同步action
export const createIncrementAsyncAction = (data,time) =>{
return (dispatch)=>{
setTimeout(()=>{
dispatch({type:'increment',data})
},time)
}
}
3.异步任务有结果后,分发一个同步的action 去真正操作数据.代码如下(示例):
4.react-redux
1.react-redux的基本使用
(1)明确两个概念:
1). UI组件: 不能做任何redux的API,只负责页面的呈现,交互等
2).容器组件:负责和redux通信,将结果交给UI组件
(2).如何创建一个容器组件—靠react-redux的connect函数
connect(mapStateToProps,mapDispatchToProps)(UI组件)
mapStateToProps:映射状态,返回值是一个对象
mapDispatchToProps:映射操作状态的方法,返回值是一个对象.
//此组件为容器组件
//导入组件
import CountUI from '../../components/Count'
import {createIncrementAction,createDecrementAction,createIncrementAsyncAction} from '../../redux/count_action'
import {connect} from 'react-redux'
function mapStateToProps(state){
return{count:state}
}
function mapDispatchToProps(dispatch){
return {
jia: number => dispatch(createIncrementAction(number)),
jian:number => dispatch(createDecrementAction(number)),
jiaAsync:(number,time) => dispatch(createIncrementAsyncAction(number,500)),
}
}
//将容器组件和组件连接起来
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)
(3)备注①:容器组件中的store是靠props传进去的,而不是在容器组件中直接引入
class App extends Component {
render() {
return (
<div>
<Count store={store}></Count>
</div>
);
}
}
备注②: mapDispatchToProps也可以是一个对象,redux会自动dispatch
export default connect(
state=>({count:state}),
{
jia: createIncrementAction,
jian:createDecrementAction,
jiaAsync:createIncrementAsyncAction,
})(CountUI)
2.react-redux数据共享到多个组件
(1)定义一个person组件,和count组件通过redux共享数据
(2) 重点:person的reducer和count的reducer要使用combineReducer进行合并,合并后的总状态是一个对象. Redux中以对象的形式存储各个组件中需要共享的数据
/*store.js文件 该文件专门用于暴露一个store 对象,整个应用只有一个store对象*/
import {applyMiddleware, createStore,combineReducers} from 'redux'
import countReducer from './reducers/count'
import personReducer from "./reducers/person";
//引入redux-thunk,用于支持异步action
import thunk from "redux-thunk";
//countReducer,personReducer 函数返回的是一个对象,是redux中需要保存的状态
//合并rducer
const allReducer = combineReducers({
he:countReducer,
rens:personReducer
})
//暴露store
export default createStore(allReducer,applyMiddleware(thunk))
(3) 交给store的是中reducer,最后注意在组件中取出状态的时候,‘取到位’.
//person.jsx
// 将容器和UI组件连接起来,把redux的状态隐射到props中 ,把改变数据的方法也隐射搭到props
//这样在UI组件中就可以得到数据也可以操作数据
export default connect(
state => ({persons:state.rens,qiuhe:state.he}),//隐射状态
//映射操作状态的方法
{
jiayiren:createAddPersonAction
})(Person)
记录:
向数组中添加一个记录,除了以下方法,还可以使用unshift,但是redux在进行页面渲染的时候,比对返回的prestate和之前的状态有没有变化,进行的是浅比较,数组的地址没有改变,就相当于判断数组没有变.所以改变数组应该使用以下方法.
//person_reducer
const initState =[{id:'001',name:'tom',age:18}]
export default function personReducer(preState = initState,action) {
const {type, data} = action
switch(type){
case 'add_person':
return [data,...preState]
default:
return preState
}
}
2.安装redux开发者工具
- 扩展程序加插件, 安装包: npm add redux-devtools-extension
- store.js 引入包
import {composeWithDevTools} from'redux-devtools-extension'
//暴露store
export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))