redux 原理图

image.png

react-redux 改的地方

自动刷新

原本的更改需要在 index.js 下 自己手动更新,react-redux 可以自动刷新

  1. store.subscribe(()=>{
  2. ReactDOM.render(<App/>,document.getElementById('root'))
  3. })

将所有组件分为两大类

  1. - **UI组件**
  2. - 只负责 UI 的呈现,不带有任何业务逻辑
  3. - 通过props接收数据(一般数据和函数)
  4. - 不使用任何 Redux API
  5. - 一般保存在components文件夹下
  6. - **容器组件**
  7. - 负责管理数据和业务逻辑,不负责UI的呈现
  8. - 使用 Redux API
  9. - 一般保存在containers文件夹下

文件夹结构的优化

优化后 两大类组件UI/容器 就都放在 containers 文件夹下了
src下:
image.png

react-redux API

Provider

让所有组件都能得到 state 数据

  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. import App from './App'
  4. import store from './redux/store'
  5. import {Provider} from 'react-redux'
  6. ReactDOM.render(
  7. <Provider store={store}>
  8. <App/>
  9. </Provider>,
  10. document.getElementById('root')
  11. )

connect 用于包装 UI 组件生成容器组件 ,非常重要!

  1. import { connect } from 'react-redux'
  2. connect(
  3. mapStateToprops,
  4. mapDispatchToProps
  5. )(UIcomponent)

mapStateToprops:将外部的数据(即state对象)转换为UI组件的标签属性
mapDispatchToProps:将分发action的函数转换为UI组件的标签属性

redux 开发者工具

chrome 商店
image.png
还需要下载工具依赖包
npm install --save-dev redux-devtools-extension
在 store.js 中调用

  1. import { createStore, applyMiddleware } from "redux";
  2. import thunk from "redux-thunk";
  3. import {composeWithDevTools} from 'redux-devtools-extension'//**
  4. import allReducers from './reducers'
  5. export default createStore(allReducers, composeWithDevTools(applyMiddleware(thunk)));//***

简述写出一个 使用到 react-redux 的组件的流程

正常写出一个 组件 作为 UI组件,没什么要注意的。这里举例用的组件名称为 Count
使用 connect 包装UI组件,并且暴露出去

src/containers/Count/index.jsx

  1. import { connect } from "react-redux";
  2. import {
  3. increment,
  4. decrement,
  5. incrementAsync,
  6. } from "../../redux/actions/count";//用于 connect 的第二个参数
  7. export default connect(
  8. state => ({
  9. count: state.counts,
  10. personNumber: state.persons.length,
  11. }),
  12. // dispatch => ({
  13. // increment: data => dispatch(createIncrementAction(data)),
  14. // decrement: data => dispatch(createDecrementAction(data)),
  15. // incrementAsync: (data, time) =>
  16. // dispatch(createIncrementAsyncAction(data, time)),
  17. // }),
  18. {
  19. increment,
  20. decrement,
  21. incrementAsync,
  22. }
  23. )(Count);

mapDispatchToProps 可以传方法也可以直接传一个对象,省略大量的 dispatch ,react-redux 会自动帮你调用 dispatch,触发对象传值的简写方式后简单明了。
connect 这里面传的东西都会作为 props 到 UI组件中,数据、方法 就都可以使用了。

src/redux/actions/count.js

然后是** /redux/actions/count**里面要写的东西,其实一般应该是 先写了这里然后再到上面的 connect 中使用。
每个 create actions 是函数,然后都是分别暴露以供 Count 组件使用,如果是异步的就是函数中返回函数。

  1. import { INCREMENT,DECREMENT } from "../constant";
  2. export const increment = data => ({type: INCREMENT,data,})
  3. export const decrement = data => ({type: DECREMENT,data,})
  4. export const incrementAsync = (data,time) => {
  5. return (dispatch)=>{
  6. setTimeout(() => {
  7. dispatch(increment(data))
  8. },time)
  9. }
  10. }

注意这里的constant文件 ,里面就是存放工程所需要的所有 action 的 type 。将 type 的字符串全部存起来,防止 coder 打错字造成低级的bug。

src/redux/count.js

后厨啦,就是接受到原料 preState 和方法 action(里面有type—干什么,data—搞多少)啦,整完再传出去 newState 啦。

  1. import { INCREMENT,DECREMENT } from "../constant";
  2. const initState = 0
  3. export default function countReducer(pre=initState, action) {
  4. const { type, data } = action;
  5. switch (type) {
  6. case INCREMENT:
  7. return pre + data;
  8. case DECREMENT:
  9. return pre - data;
  10. default:
  11. return pre
  12. }
  13. }

react-redux 在初始化时会自动调用 reducer 这时传入的第一个参数就是 undefined ,设置的初始化数据 initState 就派上用场了。

src/redux/reducers/index.js

一般后厨不止一个,那么要整合到一块成为一组传递给 store。语法也很简单,就是要用到 redux 中combineReducers这个API了

  1. import { combineReducers } from "redux";
  2. import counts from "./count";
  3. import persons from "./person";
  4. export default combineReducers({ counts, persons });

src/redux/store.js

使用 createStore 这个函数来创造一个 store,并且暴露出去。

  1. import { createStore, applyMiddleware } from "redux";
  2. import thunk from "redux-thunk";
  3. import {composeWithDevTools} from 'redux-devtools-extension'
  4. import allReducers from './reducers'
  5. export default createStore(allReducers, composeWithDevTools(applyMiddleware(thunk)));

这里的中间件"redux-thunk",是有些异步操作所需要的,别问,问就是 redux API 就是如此。
import allReducers from './reducers'这句话就是从 reduces 文件下调来一个 整合的 所有 reducers,即allReducers,第二个参数composeWithDevTools就是上面提到的 因为要使用 开发者工具的依赖包。

完成

至此就完成了 一个 Count 组件,可以从 redux 获得数据来操作了。