关于我对「Redux React-Redux」的理解

1.Redux

概述

  • Redux(作者:Dan Abramov,同时也是React核心团队成员)是 JavaScript 状态容器,提供具有响应式特性的全局状态管理
  • 作用类似于Vue.js中的Vuex,可以在组件间共享全局状态数据
  • Redux可以运行于Node.js服务器端应用、Web客户端应用、原生App应用;也可以配合jQuery、React、Angular等框架组合使用。

面试题:Redux和H5中的sessionStorage / localStorage的区别?

  • ① Redux是保存在内存中的,刷新页面即恢复初始值,无法持久化保存;sessionStorage保存在内存中,localStorage保存在磁盘中,刷新也不会丢失
  • ② Redux中的数据具有响应式特征,订阅了该数据的组件都会自动发生改变;sessionStorage / localStorage中的数据不具备响应式特征
  • ③ Redux可以用于Web客户端应用、原生App应用、Node.js服务器端应用;sessionStorage / localStorage主要应用于Web客户端页面间的数据共享

四大核心概念

安装Redux

npm i redux
  • ① state

    • 应用在当前时刻需要记录的需要具备响应式特性的数据,尤其是需要在多个组件间共享的数据,故需要集中存储

    • 例如:服务器响应数据、缓存数据、本地生成尚未持久化到服务器的数据、UI 状态数据等

    • React组件也有“状态(state)”数据,二者有本质的不同

      • ① Redux中的state是没有()setState方法的,即不能随意修改
      • ② Redux中的state用于多组件共享,而React中的state仅在当前组件中使用
      • ③ React中的state数据具有“合并”特性;而Redux中的数据修改不具备“合并”特性
  • ② action

    • 要对数据执行的动作;要想更新 state 中的数据,需要发起一个 action

    • 每个action都是一个普通 JavaScript 对象,用来描述发生想要对state执行什么操作

    • 每个action都需要有一个type属性,描述操作的目标

      • { type: ‘CHANGE_NEWS_PNO’, pno: 6 }
      • { type: ‘TOGGLE_AGREEMENT’, value: true }
      • { type: ‘SET_FAVORITE_TOPICS’, list: [10, 25, 31] }
  • ③ reducer

    • 指定对 state 执行 action 动作应该如何实现

    • reducer是一些纯函数,接收当前的state和要执行的action作为参数,返回根据action修改后的新的state对象,从而实现action想要实现的操作

    • function appReducer(state = initState, action){
          if(action.type === ' CHANGE_NEWS_PNO '){
      	        return { ...state,  newsPageNum: action.pno }
          }else if(action.type === ' TOGGLE_AGREEMENT '){
      	        return { ...state,  agreementChecked: action.value }
          }else if(action.type === ' SET_FAVORITE_TOPICS '){
      	        return { ...state,  favoriteTopics: action.list }
          }else {
      	        return state
          }
      }
      
  • ④ store

    • 状态数据存储仓库; 所有的状态最终都被存储到一个唯一的“存储仓库”中

    • 仓库的职责

      • ① 存储所有的state
      • ② 提供 getState( ) 供外界查询数据状态 —— 返回全部的状态数据
      • ③ 提供 dispatch(action) 供外界更新状态
      • ④ 通过 subscribe(listener) 注册监听器
      • ⑤ 通过 subscribe(listener) 返回的函数注销监听器
    • 在这里插入图片描述

示例1:在Node.js应用中使用Redux

const { createStore } = require('redux')
// 概念1:state
let initState = {
	registerUser: 0, //注册用户数量
	onLineUser: 0 //在线用户的数量
}

// 概念2: action 
// 概念3:reducer
function appReducer(state = initState, action) {
	console.log('---修改旧状态--');
	if (action.type === 'LOGIN') {
		return { ...state, onLineUser: state.onLineUser + 1 }
	} else if (action === 'LOGOUT') {
		return { ...state, onLineUser: state.onLineUser - 1 }
	} else if (action.type === 'ONE_REGISTER') {
		return { ...state, registerUser: state.registerUser + 1 }
	} else if (action.type === 'BATCH_REGSITER') {
		return { ...state, registerUser: state.registerUser + action.count }
	} else {
		return state
	}
}
//概念4 store
let store = createStore(appReducer)

// 查看所有的状态
// console.log(store.getState());
// 定远仓库的状态更新
store.subscribe(() => {
	console.log('-收到订阅消息,状态改变了-');
	console.log(store.getState());
})
// 使用定时器 不停的修改仓库中的状态
setInterval(() => {
	store.dispatch({ type: 'ONE_REGISTER' })
}, 1000);
setInterval(() => {
	store.dispatch({ type: 'BATCH_REGSITER', count: 10 })
}, 3000);

示例2:在React应用中使用Redux(单一文件)

import React, { useState } from 'react'
import { createStore } from 'redux';
// 状态1;state
let initState = {
  buyCount: 2
}
// 概念2 action
//  概念3 reducer
function appReducer(state = initState, action) { //1.当前值2.目标
  console.log('--state 更新了---');
  if (action.type === 'ENCREASE') {
    return { ...state, buyCount: state.buyCount + 1 }
  } else if (action.type === 'DECREASE') {
    let buyCount = state.buyCount - 1
    buyCount = buyCount < 0 ? 0 : buyCount
    return { ...state, buyCount: buyCount }
  } else {
    return state
  }
}
// 概念4 stroe
let stroe = createStore(appReducer)
function CartShow() {
  let [count, setCount] = useState(stroe.getState().buyCount)
  // 订阅仓库状态的修改
  stroe.subscribe(() => {
    setCount(stroe.getState().buyCount)
  })
  return <div>当前的商品数量:{count}</div>
}

function CartModify() {
  return (
    <>
      <button onClick={() => { stroe.dispatch({ type: 'DECREASE' }) }}>-</button>
      <button onClick={() => { stroe.dispatch({ type: 'ENCREASE' }) }}>+</button>
    </>
  )
}
export default function App() {
  return (
    <div>
      <CartShow />
      <hr />
      <CartModify />
    </div>
  )
}

2.React-Redux

问题

  • 在多模块文件的React应用中,如果在根模块中创建 Redux store,然后通过props依次传递给所有的子组件,实在太麻烦了

方案

  • react-redux模块可用于使用了Redux的React项目中,提供了两方面的扩展功能

    • ① 一个“Context.Provider”:为它所包含的所有子组件提供store使用
    • ② 一个HOC高阶组件函数:connect()函数将自定义组件提升为“高阶组件”,将Redux的dispatch和state映射为被包装组件的props

步骤

  • ① 安装依赖模块 npm i redux react-redux
  • ② 顶级组件中创建 store 和 reducer,使用Provider为子组件共享store
  • ③ 将store.dispatch()映射为子组件的props
  • ④ 将store.getState()映射为子组件的props

index.js:

import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import CartModify from './components/CartModify';
import CartShow from './components/CartShow';
// 1.state
let initState = {
  byCount: 1
}
// 2.action

// 3.reducer
function appReducer(state, action) {
  switch (action.type) {
    case 'ENCREASE':
      return { ...state, byCount: state.byCount + 1 }
    case 'DECREASE':
      return { ...state, byCount: state.byCount - 1 }

    default:
      return initState
  }
}
// 4.store
let store = createStore(appReducer)

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <CartShow />
    <hr />
    <CartModify />
  </Provider>
);

CartShow.js:

import React from 'react'
import { connect } from 'react-redux';
function CartShow(props) {
	console.log('props1', props);
	return (
		<div>当前购物车中的购买数量:{props.bc}</div>
	)
}
function mapStateToProps(state) {
	console.log('state1', state);
	return {
		bc: state.buyCount
	}
}
export default connect(mapStateToProps, null)(CartShow)

CartModify.js:

import React from 'react'
import { connect } from 'react-redux';
function CartModify(props) {
	console.log(props);
	return (
		<div>
			<button onClick={props.dec}>-</button>
			<button onClick={props.enc}>+</button>
		</div>
	)
}
function mapDispatchToProps(dispatch) {
	return {
		enc: () => {
			dispatch({ type: 'ENCREASE' })
		},
		dec: () => {
			dispatch({ type: 'DECREASE' })
		}
	}
}
export default connect(null, mapDispatchToProps)(CartModify)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

捂耳听枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值