阅读:46
store:仓库,是一个容器,主要用于集中管理应用中的状态
state:状态,是各组件需要共享的状态数据
action:是一个普通对象,通常用于描述发生了什么。这个对象中一般有两个属性:type 和 payload
action creator:action 创建函数,是一个函数结构,主要用于创建 action 对象,以实现 action 的复用
reducer:是用于同步更新状态数据的纯函数。该函数以 state 和 action 作为参数,返回新的 state 状态数据。函数签名是:(state, action) => newState
注:纯函数
返回值依赖于参数
函数主体内部不产生任何副作用
Reducer 必需符合以下规则:
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中
唯一改变 state 的方法就是触发 action(即调用 dispatch(action) 方法),action 是一个用于描述已发生事件的普通对象
为了描述 action 如何改变 state tree ,你需要编写 reducers
/** action type 的取值 */
export const ADD_TO_CART = Symbol('add_to_cart')
/**
* 定义 action creator (action创建函数),用于创建 action 对象,以便于复用 action 对象
*/
import { ADD_TO_CART } from "./constants"
/**
* 用于创建添加到购物车时使用的 action 对象
*/
export const addToCartAction = (product) => {
return {
type: ADD_TO_CART,
payload: product,
}
}
/**
* 实现购物车状态数据管理
*/
import _ from 'lodash'
import { ADD_TO_CART, REMOVE_FROM_CART } from "../actions/constants"
/**
* 初始状态数据
*/
const initialState = {
cart: [],
}
/**
* reducer 函数,是一个纯函数,用于同步更新状态数据
* @param {*} state 旧状态数据
* @param {*} action action对象,有 type 和 payload 属性
* @returns 返回新的状态数据
*/
const cartReducer = (state = initialState, { type, payload }) => {
/** 对 state 进行深克隆 */
const copyState = _.cloneDeep(state)
/**
* 使用 switch 多分支选择,来判断当前 action 的动作类型
*/
switch (type) {
case ADD_TO_CART: // 添加购物车
copyState.cart.push(payload)
return copyState
case REMOVE_FROM_CART: // 从购物车中删除商品
copyState.cart = copyState.cart.filter(prod => prod.id !== payload.id)
return copyState
default:
return state
}
}
export default cartReducer
/**
* 将多个独立的 reducer 合并为一个根 reducer
*/
import { combineReducers } from 'redux'
import cartReducer from './cart'
const rootReducer = combineReducers({
shoppingCart: cartReducer,
})
export default rootReducer
/**
* 创建 Store 仓库
*/
import { createStore } from 'redux'
import rootReducer from '../reducers'
/**
* 基于根 reducer 来创建 store
*/
const store = createStore(rootReducer)
export default store
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import {Provider} from "react-redux";
import store from "./store";
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById('root')
)
import React from 'react'
import {useDispatch, useSelector} from "react-redux"; // 引入并结构出useDispatch(使用方法,改变数据)useSelector(拿到数据)
impot {addToCartActio} fron "../actions/cart.js"
function React() {
const dispatch=useDispatch()
const cart=useSelector(state=>state.shoppingCart.cart) // 格式一个回调函数,state.空间名字.仓库数据名字
const clickHandler=()=>{
dispatch(addToCartAction({id:0,title:'商品信息'})) // 触发的actions事件
}
return (
<div onClick={clickHandler}>react</div>
)
}
export default React
import {createStore,applyMiddleware} from "redux";
import logger from 'redux-logger' // 记录仓库状态数据
import thunk from 'redux-thunk' // 异步仓库任务处理
import rootReducer from "../reducers/index"
const store = createStore(rootReducer,applyMiddleware(logger,thunk))
export default store
import {LOGIN_SUCCESS,LOGIN_FAILED,LOGIN_RESET} from '../constants/action-types'
import {postLogin} from '../api/user'
export const loginSuccessAction=info=>{
return {
type:LOGIN_SUCCESS,
payload:info,
}
}
// 重置
export const loginResetAction=()=>{
return{
type: LOGIN_RESET,
}
}
// 异步请求登录网络
export const loginAsyncAction=(info)=>{
/**
* 返回的这个函数,会自动被 redux-thunk 中间件调用执行。
* 在调用执行这个函数时,会自动传递 dispatch 作为参数。
* 不要求返回的这个函数保持纯净(即可以包含异步逻辑)
*/
return async dispatch=>{
const {status,data}=await postLogin(info)
if(status===200){ // 登录成功
dispatch(loginSuccessAction(data))
return true
}else { // 登录失败
dispatch({
type:LOGIN_FAILED
})
return false
}
}
}