第一章:React基础知识(React基本使用、JSX语法、React模块化与组件化)(一)
第二章:React基础知识(组件实例三大核心属性state、props、refs)(二)
第三章:React基础知识(事件处理、受控组件与非受控组件、高阶函数、组件的生命周期)(三)
第四章:React脚手架应用(创建脚手架、代理配置、ajax相关、组件通信)(四)
第五章:react-router5路由相关一(路由相关概念、基本使用、NavLink与NavLink的封装、Switch的使用、严格匹配、路由重定向、路由组件与一般组件的区别)(五)
第六章:react-router5路由相关二(嵌套路由、路由传参、replace、编程式路由导航、withRouter的使用、BrowserRouter与HashRouter的区别)(六)
第七章:React-Router6路由相关一(路由的基本使用、重定向、NavLink·、路由表、嵌套路由)(七)
第八章:React-Router6路由相关二(路由传参、编程式路由导航、路由相关hooks)(八)
第九章:React相关扩展一(setState、lazyLoad、Hooks相关)(九)
第十章:React相关扩展二(Fragment、Content、组件优化、render props、错误边界)(十)
第十一章:Redux相关知识(什么是redux、redux的工作原理、redux的核心概念、redux的基本使用)(十一)
第十二章:React-Redux相关知识(什么是react-redux、react-redux的原理、react-redux相关API、react-redux的基本使用)(十二)
Redux
是 JavaScript应用的状态容器
,提供可预测的状态管理。可以开发出行为稳定可预测的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。Redux
是一个使用叫做“action”
的事件来管理和更新应用状态的模式和工具库
,它以集中式Store的方式对整个应用中使用的状态进行集中管理
,其规则确保状态只能以可预测的方式更新。Redux
提供的模式和工具使您更容易理解应用程序中的状态何时、何地、为什么以及如何更新
,以及当这些更改发生时您的应用程序逻辑将如何表现。- 类似于vuex 但是不同于vuex,可以对状态进行管理。
页面初始渲染时:
store 调用一次 root reducer
,并将返回值保存为它的初始 state
UI 组件访问 Redux store 的当前 state
,并使用该数据来决定要呈现的内容。监听store 的更新
,以便他们可以知道 state 是否已更改。页面更新渲染时:
dispatch
一个 action
到 Redux store
,例如 dispatch({type:'counter/increment'})
store
用之前的 state
和当前的 action 再次运行 reducer 函数
,并将返回值保存为新的 state
store
通知所有订阅过的 UI
,通知它们 store 发生更新
发现数据被更新
的每个组件都强制使用新数据重新渲染
,紧接着更新网页
。应用的整体全局状态
以对象树的方式存放于单个 store
。 唯一改变状态树的方法
是创建 action
,一个描述发生了什么的对象,并将其 dispatch 给 store
。 要指定状态树如何响应 action 来进行更新
,你可以编写纯 reducer 函数
,这些函数根据旧 state 和 action 来计算新 state
。
let state = {
todos:[],
params:{}
}
Action
Action
描述当前发⽣的事情。改变State的唯⼀办法
,就是使⽤Action。它会运送数据到 Store。action
内必须使⽤
⼀个字符串类型的 type字段
来表示将要执⾏的动作
。{ type: 'ADD_TODO', text: '去游泳馆' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'completed' }
Action Creator
action creator
是一个创建并返回一个 action 对象的函数
。它的作用是让你不必每次都手动编写 action对象
示例代码:
const addTodo = data => ({type: 'todos/todoAdded',data})
reducer
是一个函数
,接收当前的state和一个action 对象
,必要时决定如何更新状态,并返回新状态。函数签名是:(state, action) => newState
。可以将reducer 视为一个事件监听器,它根据接收到的action(事件)类型处理事件。
Reducer 必需符合以下规则:
仅使用 state 和 action 参数计算新的状态值
禁止直接修改 state
。必须通过复制现有的 state 并对复制的值进行更改的方式来做不可变更新禁止任何异步逻辑、依赖随机值或导致其他“副作用”的代码
reducer 函数内部的逻辑通常遵循以下步骤:
示例代码:
// 初始化状态
const initialState = { value: 0, index: 1 }
function counterReducer(preState=initialState, action) {
//从action对象中获取:type、data
const {type,data} = action
//根据type决定如何加工数据
switch (type) {
case 'increment': //如果是加
return {
...preState
value:preState.value + data
}
case 'decrement': //若果是减
return {
...preState
value:preState.value - data
}
default:
// 返回prestate 不变
return preState
}
}
当前 Redux 应用的状态存在于
一个名为 store
的对象中。store
是通过传入一个reducer来创建的
,并且有一个getState 的方法
,它返回当前状态值
。
Store
就是保存数据的地⽅,可以把它看成⼀个容器。整个应⽤只能有⼀个Store。Redux提供createStore
这个函数,⽤来⽣成Store
。
示例代码:
//引入createStore,专门用于创建redux中最为核心的store对象
// 旧版本的引入
// import {createStore} from 'redux'
// 新版本的引入
import { legacy_createStore as createStore } from 'redux'
//引入为Count组件服务的reducer
import reducer from './reducer'
//暴露store
export default createStore(reducer)
/* 如果该仓库用多个reducer,则使用combineReducers函数来合并reducer,
可以通过combineReducers组合多个Reducer,然后通过createStore来创建状态机。*/
const store2=createStore(combineReducers({
todos,
counter,
}));
或者直接使用@reduxjs/toolkit包中的configureStore方法来生成store
import { configureStore } from '@reduxjs/toolkit'
const store = configureStore({ reducer})
仓库创建好了之后,将store引入到需要使用仓库的组件中。
import store from './store/index.js'
// 分发动作
store.dispatch({type:'',data:''})
// 获取仓库数据
store.getState();
Redux store 有一个方法叫 dispatch
。更新 state 的唯一方法
是调用 store.dispatch() 并传入一个action对象
。store 将执行所有reducer函数并计算出更新后的state,调用 getState()
可以获取新state。
示例代码:
store.dispatch({ type: 'counter/increment' })
console.log(store.getState())
// {value: 1}
dispatch 一个 action 可以形象的理解为 "触发一个事件"
。发生了一些事情,我们希望 store
知道这件事。Reducer 就像事件监听器一样,当它们收到关注的 action 后,它就会更新 state 作为响应。 我们通常调用 action creator 来调用 action
:
示例代码:
const increment = () => {
return {
type: 'counter/increment'
}
}
// 分发动作
store.dispatch(increment())
console.log(store.getState())
添加一个变化监听器
。每当dispatch action 的时候就会执行
,state
树中的一部分可能已经变化。你可以在回调函数里调用 getState() 来拿到当前 state
。你可以在变化监听器里面进行
dispatch(),如果需要解绑这个变化监听器,执行 subscribe 返回的函数即可。
参数listener (Function): 每当 dispatch action 的时候都会执行的回调
。state 树中的一部分可能已经变化。你可以在回调函数里调用 getState() 来拿到当前 state。
返回值(Function): 一个可以解绑变化监听器的函数。
// 监听方法一
store.subscribe(() => {
this.setState({
...store.getState()
});
}); //订阅者做的事情
// 监听方法二
store.subscribe(()=>{
ReactDOM.render(<App/>,document.getElementById('root'))
})
安装
npm install redux
主要API
createStore(reducer, [preloadedState], [enhancer])
创建仓库combineReducers(reducers)
合并reducerapplyMiddleware(...middlewares)
应用中间件store相关API
store.getState()
获取仓库中的状态store.dispatch(action)
分发到某个动作store.subscribe(listener)
订阅仓库内状态更新replaceReducer(nextReducer)
替换reducer代码案例片段:
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import store from './redux/store'
ReactDOM.render(<App/>,document.getElementById('root'))
store.subscribe(()=>{
ReactDOM.render(<App/>,document.getElementById('root'))
})
App.js
import React, { Component } from 'react'
import Count from './components/Count'
export default class App extends Component {
render() {
return (
<div>
<Count/>
</div>
)
}
}
redux/count_action.js(该文件专门为Count组件生成action对象)
//同步action,就是指action的值为Object类型的一般对象
export const createIncrementAction = data => ({type:'increment',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/count_reducer.js
/*
1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
const initState = {
value:0,index:1
}
//初始化状态
export default function countReducer (preState = initState, action) {
console.log('preState:',preState);
console.log('action:',action);
//从action对象中获取:type、data
const { type, data } = action
//根据type决定如何加工数据
switch (type) {
case 'increment': //如果是加
return {
...preState,
value: preState.value + data
}
case 'decrement': //若果是减
return {
...preState,
value: preState.value - data
}
default:
return preState
}
}
redux/store.js
/*
该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
// 旧版
// import { createStore } from 'redux'
//新版
import { legacy_createStore as createStore, applyMiddleware } from 'redux'
//引入为Count组件服务的reducer
import countReducer from './count_reducer'
//引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'
//暴露store
export default createStore(countReducer, applyMiddleware(thunk))
components/Count.jsx
import React, { Component } from 'react'
//引入store,用于获取redux中保存状态
import store from '../../redux/store'
//引入actionCreator,专门用于创建action对象
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
export default class Count extends Component {
state = {carName:'奔驰c63'}
/* componentDidMount(){
//检测redux中状态的变化,只要变化,就调用render
store.subscribe(()=>{
this.setState({})
})
} */
//加法
increment = ()=>{
const {value} = this.selectNumber
store.dispatch(createIncrementAction(value*1))
}
//减法
decrement = ()=>{
const {value} = this.selectNumber
store.dispatch(createDecrementAction(value*1))
}
//奇数再加
incrementIfOdd = ()=>{
const {value} = this.selectNumber
const count = store.getState()
if(count % 2 !== 0){
store.dispatch(createIncrementAction(value*1))
}
}
//异步加
incrementAsync = ()=>{
const {value} = this.selectNumber
// setTimeout(()=>{
store.dispatch(createIncrementAsyncAction(value*1,500))
// },500)
}
render() {
return (
<div>
<h1>当前求和为:{store.getState()}</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>
)
}
}