redux

redux的使用

单页应用越来越复杂,如react项目,状态复杂难以管理,redux可以很好地处理数据。

三个原则

  1. 单一数据源,应用的state存储在一个树上,这个树存储在唯一的store中

  2. state只读,不是不能修改,唯一改变 state 的方法就是触发 action

  3. 使用纯函数来执行修改

    构建一个最简单的redux案例

    create-react-app脚手架创建一个react项目,删除多余代码,目录结构如下:
    mulu
    实现功能:两个按钮,加好按钮和减号按钮,每次点击数据变化1

  4. 首先构建页面基本结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    export default () => {
    const [n, setn] = useState(0);
    const plus = () => {

    };
    const del = () => {

    };
    return (
    <div>
    <Button type="primary" onClick={plus}>
    +
    </Button>
    <Button type="primary" onClick={del}>
    -
    </Button>
    <div>{n}</div>
    </div>
    );
    };
  5. 写action,实际上就是对象,这里我们用函数的形式创建action,注意必须要有type属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    export const addOne = (value) => {
    return {
    type: 'addOne',
    value: value + 1
    }
    }
    export const delOne = (value) => {
    return {
    type: 'delOne',
    value: value - 1
    }
    }

    分别对应加和减操作,到时候把操作的数据传进来就好了。

  6. reducer
    action是会传给reducer进行处理的,reducer会接受两个参数,state和action,一般会给state附一个初始值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    export default (state = 0, action) => {
    console.log('ok', state);
    switch (action.type) {
    case 'addOne':
    return state + 1
    case 'delOne':
    return state - 1
    default:
    return state
    }
    }

    要注意case后的名称不能写错,而且必须有返回值,也就是反会处理好之后的状态才行。

  7. 创建store

    1
    2
    3
    4
    5
    const store = createStore(
    reducer,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );
    export default store
  8. 在Home组件中使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    export default () => {
    const [n, setn] = useState(0);
    useEffect(() => {
    //subscribe用于监听状态的变化
    store.subscribe(() => {
    //用getState方法获取reducer中return的值,每当加和减后都会获取最新的值
    const newn = store.getState();
    setn(newn);
    });
    });
    const plus = () => {
    //创建action,把当前状态传进去dispatch给reducer
    const action = addOne(n);
    store.dispatch(action);
    };
    const del = () => {
    const action = delOne(n);
    store.dispatch(action);
    };
    return (
    <div>
    <Button type="primary" onClick={plus}>
    +
    </Button>
    <Button type="primary" onClick={del}>
    -
    </Button>
    <div>{n}</div>
    </div>
    );
    };

    这样最简单的redux就实现了,感觉还是有点复杂的,但是在项目越写越复杂的时候,就能体会到redux的好处了。
    该案例git地址

react-redux

接下来使用react-redux实现一样的功能,页面结构调整一下。
pic
react-redux有两个核心点—Provider和connect

  1. Provider用来包裹根组件App组件
  2. connect用来形成高阶组件,他有两个常用参数,mapStateToProps,mapDisPatchToProps,基本上就是一个接收state一个发送action,从名字也能大概了解,用connect方法形成的高阶组件,可以在被包裹组件内部用props获取,connect参数的返回值。

    reducer

    代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    export const reducer = (state = { count: 0 }, action) => {
    switch (action.type) {
    case 'add':
    return { count: state.count + 1 }
    case 'del':
    return { count: state.count - 1 }
    default:
    return state
    }
    }

    A组件只有两个按钮,分别实现加和减

    代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    import { connect } from 'react-redux'

    function A(props) {
    const handleAdd = () => {
    //就是dispatch({type: 'add'})
    props.addOne()
    }
    const handleDel = () => {
    //就是dispatch({type: 'del'})
    props.delOne()
    }
    return (
    <>
    <button onClick={handleAdd}>+</button>
    <button onClick={handleDel}>-</button>
    </>
    )
    }
    const mapDispatchToProps = dispatch => {
    //返回一个对象,在A组件中可以用props.addOne()/props.delOne()调用这两个函数,达到dispatch(action)的作用
    return {
    addOne: () => {
    //相当于store.dispatch
    dispatch({
    type: 'add'
    })
    },
    delOne: () => {
    //相当于store.dispatch
    dispatch({
    type: 'del'
    })
    }
    }
    }
    // 只发送,第一个参数填null即可,用connect对A组件加强
    export default connect(null, mapDispatchToProps)(A)

    B组件只显示值

    代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import { connect } from 'react-redux'

    function B(props) {
    return (
    <div className="App">
    {props.count}
    </div>
    );
    }
    const mapStateToProps = (state) => {
    //接收reducer的返回对象,在B组件中用props.的方式使用数据
    return state
    }
    //只接收返回的state,只需要第一个参数即可
    export default connect(mapStateToProps)(B);
    这样就用react-redux实现了同样的功能。
    该案例git地址
上一篇

http