Redux基础知识学习

82 阅读2分钟

1.什么是Redux

Redux是一个管理状态(数据)的容器,提供了可预测的状态管理

2.什么是可预测的状态管理?

数据 在什么时候,因为什么,发生了什么改变,都是可以控制和追踪的,称之为预测的状态管理

3.为什么要使用Redux

  • React是通过数据驱动界面更新的,React负责更新界面,而我们负责管理数据
  • 默认情况下我们可以在每个组件中管理自己的状态, 但是现在前端应用程序已经变得越来越复杂
    • 状态之间可能存在依赖关系(父子、共享等),一个状态的变化会引起另一个状态的变化
  • 所以当应用程序复杂的时候, 状态在什么时候改变,因为什么改变,发生了什么改变,就会变得非常难以控制和追踪
  • 所以当应用程序复杂的时候,我们想很好的管理、维护、追踪、控制状态时, 我们就需要使用Redux

4.Redux核心理念

  • 通过store来保存数据
  • 通过action来修改数据
  • 通过reducer将store和action串联起来
                    -------------
        --------->  | Component |  ---------
       |            -------------           |
       |                                    ↓
-------------       -------------       -------------
|   Store   | <---- |  Reducer  | <---- |  Action   |
-------------       -------------       -------------

5.Redux三大原则

三大原则

  • 单一数据源
    • 整个应用程序的state只存储在一个 store 中
    • Redux并没有强制让我们不能创建多个Store,但是那样做并不利于数据的维护
    • 单一的数据源可以让整个应用程序的state变得方便维护、追踪、修改
  • state是只读的
    • 唯一修改State的方法一定是触发action,不要试图在其他地方通过任何的方式来修改State
    • 这样就确保了View或网络请求都不能直接修改state,它们只能通过action来描述自己想要如何修改stat;
    • 这样可以保证所有的修改都被集中化处理,并且按照严格的顺序来执行,所以不需要担心race condition(竟态)的问题;
  • 使用纯函数来执行修改
    • 通过reducer将 旧state和 action联系在一起,并且返回一个新的State:
    • 随着应用程序的复杂度增加,我们可以将reducer拆分成多个小的reducers,分别操作不同state tree的一部分
    • 但是所有的reducer都应该是纯函数,不能产生任何的副作用

5.1 纯函数

纯函数是返回结果只依赖于它的参数,并且在执行过程里面没有负作用

// 纯函数
function sum(num1, num2){
    return num1 + num2;
}

// 非纯函数
let num1 = 10;
function sum(num2){
    return num1 + num2;
}

// 纯函数
const num1 = 10;
function sum(num2){
    return num1 + num2;
}

6.基本使用

const redux = require('redux')
const ADD_COUNT = 'ADD_COUNT'
const SUB_COUNT = 'SUB_COUNT'
// 定义一个状态
let initialState = {
    count: 0
}
// 利用store来保存状态(state)
const store = redux.createStore(reducer)
// 利用action来修改状态
const addAction = (num) => { return { type: ADD_COUNT, num } }
const subAction = (num) => { return {type: ADD_COUNT, num} }
// 利用reducer将store和action串联起来
function reducer(state = initialState, action) {
    switch (action.type) {
        case ADD_COUNT:
            return { count: state.count + action.num }
        case ADD_COUNT:
            return { count: state.count + action.num }
        default:
            return state
    }
}
store.subscribe(() => {
    console.log(store.getState())
})
console.log('store.getState()', store.getState())
store.dispatch(addAction(11))

store

redux-store

  • getState()获取state
  • dispatch(action)更新state
  • subscribe(listener)注册监听器
  • subscribe(listener)返回的函数注销监听器

image.png

// action
import { ADD_COUNT } from "./constants"
export const addAction = (num) => {
    console.log('num', num)
    return {
        type: ADD_COUNT,
        num
    }
}
// constant.js
// 为书写错误时能有提示
export const ADD_COUNT = 'ADD_COUNT'
// index.js
import { createStore } from "redux"
import reducer from "./reducer"
const store = createStore(reducer)
export default store
// reducer.js
import { ADD_COUNT } from "./constants"
const initialState = {
    count: 1
}
const reducer = (state = initialState, action) => {
    switch (action.type) {
        case ADD_COUNT:
            return { count: state.count + action.num }
        default:
            return state
    }
}
export default reducer

使用

import React from "react"
import { BrowserRouter, NavLink } from "react-router-dom"
import DefineRoutes from './router/index'
import store from "./store"
import { addAction } from "./store/action"
import './App.css'

class App extends React.PureComponent {
    constructor (props) {
        super(props)
        this.state = {
            count: store.getState().count
        }
    }
    componentDidMount() {
        store.subscribe(() => {
            console.log('xiugaile', store.getState().count)
            this.setState({
                count: store.getState().count
            })
        })
    }
    changeCount() {
        console.log('change')
        store.dispatch(addAction(20))
    }
    render() {
        let obj = {
            name: 'sss',
            age: 16,
            gender: 'man'
        }
        return (
            <div id={'app'}>
                <BrowserRouter>
                    <nav id="sidebar">
                        <NavLink to={'/home'} state={obj}>Home</NavLink>
                        <NavLink end to={'/about'}>About</NavLink>
                        <NavLink end to={'/user'}>User</NavLink>
                    </nav>
                    <button onClick={() => this.changeCount()}>change</button>
                    <>{this.state.count}</>
                    <DefineRoutes></DefineRoutes>
                </BrowserRouter>
            </div>
        )
    }
}
export default App