redux

为什么要使用状态管理

  1. 多个组件共用一个状态
  2. 状态管理,便于更新和维护

为什么React需要状态管理?

  1. react不是MVC框架,单纯可以看做是V(视图层框架),缺失了M和C,
  2. 在flux/redux/mobx中,react是他们的构成部分

redux的项目用法

  1. 工具
    • redux
    • react-redux 数据分块
    • redux-thunk/redux-saga redux中的数据请求
    • redux-devtools-extension 用于激活浏览器中redux扩展插件
  2. 安装一个redux chrome扩展插件: redux-devtools
  3. 构建四个部分
    • store
    • actionCreators/actions
    • reducers
    • View

redux基本了解

  1. redux是flux进阶版
  2. redux要求数据修改必须是纯函数
  3. redux的state是只读的,唯一的
    • redux的state只能定义一个初始值
    • 要求你拷贝

redux流程图

  1. 构成部分

    • store 存储管理数据
    • React Component 视图
    • ActionCreators 动作创建者
    • Reducers 派发器 用于修改数据,并且返回一个新的状态值
  2. Flow

    • React --> ActionCreators --> Reducers -> Store --state-> React
  3. 案例实现

redux_single_demo

  • redux计数案例
    flow:
    1.首先打造redux中的 store
    2.reducer.js 1)定义初始状态 ; 2)对初始状态进行拷贝,并将拷贝后的新状态return出去
    3.组件中使用数据 1)组件中定义个状态来接受数据 ; 2)改数据的过程
    4.actionCreators.js中定义方法 1)创建动作 ; 2)发送动作 - store来发
    5.constant.js中定义动作的常量
    6.reducer接受到store发送过来的动作,判断动作的类型,修改数据
    7.useEffect进行视图的更新

src/store/index.js

import {createStore} from 'redux' //封装好了事件的订阅发布功能
import reducer from './reducer'
const store = createStore(reducer)

export default store 

src/store/reducer.js

import {INCREMENT} from './constant'
//! 1. 定义初始状态
const initState = {
    count: 0,
    data: {
        name: 'eason'
    }
}
//reducer是一个纯函数              初始状态            动作
export default function reducer (state = initState,action) {
    // const newState = Object.assign({},state)
    // const newState = Object.create({},state)
    const newState = JSON.parse(JSON.stringify(state))//redux的state是只读的,唯一的,要求你拷贝
    // const newState = 递归深拷贝【自己封装、loadsh】
    // const newState = 使用第三方的一个库【Immutable】
    console.log('reducer')
    switch (action.type) {
        case INCREMENT:
            newState.count ++
            break;
    
        default:
            break;
    }

    return newState//返回一个新状态
}

src/store/constant.js

export const INCREMENT= 'INCREMENT'

src/store/actionCreators.js

import {INCREMENT} from './constant'
import store from './index'
export default {
    //1.创建动作
    increment () {
        console.log('actions')
        const action = {
            type: INCREMENT
        }
        //2.发送动作 - store来发
        store.dispatch(action)
    }
}

App.js

import React,{useState,useEffect} from 'react'
import store from './store'
import actions from './store/actionCreators'
export default function App() {
  const [count,setCount] = useState(store.getState().count)//redux自己封装的
  function add () {
    actions.increment()
  }
  useEffect(() => {
    store.subscribe(() => {
      setCount(store.getState().count)
    })
  },[])
  return (
    <div>
      <button onClick={add}> + </button>
        {count}
    </div>
  )
}

项目中的redux

  • redux计数案例

src/store/index.js

import {createStore,applyMiddleware} from 'redux'//createStore封装好了事件的订阅发布功能
import thunk from 'redux-thunk'//中间件 处理redux异步的数据请求
import {composeWithDevTools} from 'redux-devtools-extension'//激活谷歌的拓展插件
import rootReducer from '../reducers'
/*
    * rootReducer  项目中最大的reducer,用于管理项目中其他的reducer
    * createStore(reducer,redux需要的中间件)
*/
export default createStore(rootReducer,composeWithDevTools(applyMiddleware(thunk)))

src/reducers/index.js

import {combineReducers} from 'redux'
import count from './count/reducer'
import list from './list/reducer'
export default combineReducers({
    //里面存放的就是其他reducers 
    count,list
})

src/reducers/count/reducer.js

import {INCREMENT} from '../../constant'
//1.定义初始状态
const initState = {
    n: 0
}
export default function reducer (state = initState,action) {
    switch (action.type) {
        case INCREMENT:
            state.n++
            return {...state}
            break;
    
        default:
            return {...state}
            break;
    }
}

src/constant/index.js

export const INCREMENT = 'INCREMENT'

export const GET_LIST = 'GET_LIST'

src/actions/count/index.js

import {INCREMENT} from '../../constant'
export default {
    increment () {
        //! 这里没有发起数据请求
        //! 这里我们只需要给一个返回值,这个返回值就是action
        return {
            type: INCREMENT
        }
    }
}

index.js - 入口文件

import store from './store'
//通过跨组件通信来获取数据
import {Provider} from 'react-redux'
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

src/pages/Count.js

import React from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import actions from '../actions/count'
function Count (props) {
    const {n,increment} = props 
    return (
        <div>
            <button onClick={increment}> + </button>
            <p> { n } </p>
        </div>
    )
}

/* 
    * 第一个参数是用于帮助我们获取store中的数据的
    * 第二个参数是用于帮助我们获取actions中的方法,并将actions中创建的action发给reducer
*/
function mapStateFromProps (state) {
    return {n: state.count.n}
}
function mapDispatchFromProps (dispatch) {
     //actions就是把actions里的方法作成属性绑定在组件身上
    //dispatch就是用dispatch来发送actions里的动作;actions里的动作全部都是actions文件中return的返回值
    return bindActionCreators(actions,dispatch)
}
//connec函数的返回值是一个高阶组件
export default connect(mapStateFromProps,mapDispatchFromProps)(Count)
  • redux数据请求案例

src/reducers/list/reducer.js

import {GET_LIST} from '../../constant'
//1.定义初始值
const initState = {
    list: []
}
export default function reducer (state = initState,action) {
    const newState = JSON.parse(JSON.stringify(state))
    switch (action.type) {
        case GET_LIST:
            newState.list = action.payload//数据请求的返回值进行赋值
            return newState
            break;
    
        default:
            return newState
            break;
    }
}

src/actions/list/index.js

import {GET_LIST} from '../../constant'

export default {
    getList ({reqType,cid}) {
        //进行数据请求的 
        // return {type}
        //! 异步数据请求这里返回的是一个以dispatch为参数的回调函数,因为异步数据请求很难写return的
        return dispatch => {
            // 1. 进行数据请求
            // 2. 将数据请求结果作为action的一部分,发给reducer
            fetch(`http://59.110.226.77:3000/api/list/${reqType}?cid=${cid}`)
                .then(data => data.json())
                .then(res => {
                    dispatch({
                        type: GET_LIST,
                        payload: res.data.content
                    })
                })
                .catch(error => Promise.reject(error))
        }
    }
}

src/pages/List.js

import React,{useEffect} from 'react'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import actions from '../actions/list'

function List (props) {
    const {list,getList} = props 
    useEffect(() => {
        getList({
            reqType: 'hot',
            cid: 17
        })
    },[list])
    if (list.length == 0) {
        return <div> 数据为空 </div>
    }
    return (
        <div>
            <button onClick={() => { getList({reqType: 'hot',cid: 17 }) }}>人气</button>
            <button onClick={() => { getList({reqType: 'price',cid: 17 }) }}>价格</button>
            <button onClick={() => { getList({reqType: 'sell',cid: 17 }) }}>销量</button>
            <button onClick={() => { getList({reqType: 'latest',cid: 17 }) }}>最新</button>
            {list.map(item => <div key={item.id}> { item.d_title} </div>)}
        </div>
    )
}
export default connect(
    state => state.list,
    dispatch => bindActionCreators(actions,dispatch)
)(List)

文件夹目录
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值