欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Redux小白学习笔记

程序员文章站 2022-07-02 22:46:22
...

Redux

本篇学习笔记是针对自己的项目所写的,所以有看不懂的地方要或者更多的注释和细节需要参加全栈小项目(react+redux+koa+mongo)中的(/client/src)部分,欢迎点赞支持~

简介

首先关于react中redux环境的搭建:
cnpm i redux react-redux redux-thunk
这三个分别依赖一般是都要安装的,
第一个不说了,
第二个是关联react和redux的桥梁,大致原理是通过一个闭包生成一个数据中心store,然后把这个store绑定到React的顶层props里面,子组件通过HOC建立与顶层props.store的联系,进而获取数据、修改数据、更新UI
第三个是为了解决异步问题。

首先挂一下阮一峰老师的图片Redux小白学习笔记

  1. 用户通过component即view层触发事件,事件逻辑中遇到state改变就调用dispatch分发Action给store
  2. Store 调用 Reducer,并向Reducer传入两个参数:当前 State 和收到的 Action 对象
  3. Reducer中进行判断后生成新state再次转发给store,store提交新state给component接收
  4. component接收到改变的state后自动重新渲染
    其实如果说子组件不涉及交互功能,只是单纯的数据展示的话,那么没必要用redux,直接父组件用redux,然后将属性传递给子组件就好

Store

首先创建Store.js文件,Store就是保存数据的地方,利用createStore()生成,整个应用要保持Store的唯一性。
createStore()中有三个参数:reducer, initialState, enhancer
  reducer :function 类型。一个传入 current state (当前state) 和 要处理的 action ,返回新的 state tree 的函数。
  initialState:可以是任何类型。初始的state。如果你使用 combineReducers 去生产根 reducer 函数,它必须是一个与 combineReducer 的键相同的对象。
  enhancer:function 类型。store 的增强器。你可以选择指定它来增加具有第三方第三方能力的 store。唯一一个跟 Redux 一起使用的 enhancer 是 applyMiddleware()

action

创建actions文件夹,其中按照事件的类型进行分类创建Action.js
其中最重要的是描述view层发出的通知,通俗的说就是事件中代码逻辑的主要书写场所,最终的目的是dispatch出一个action对象(action对象是一个用于描述已发生事件的普通JS对象,必须携带type属性)
当action对象被发出时,就会被State送给Reducer自动进行状态的更新。
Reducer 函数不用手动调用,store.dispatch方法会触发 Reducer 的自动执行。为此,Store 需知道Reducer,做法就是在createStore时,传入Reducer

Reducer

创建Reducer文件夹,其中按照事件的类型进行分类创建Reducer.js
其中最重要的是根据action对象携带的type来返回不同的State实现对state的更新,值得注意的是Reducer是一个纯函数(一种编程概念),意味着同样的输入,必定得到同样的输出。

{      //  for example,纯函数内不能修改state,必须返回一个全新的对象
        ...state,
        posts: state.posts.map(post => // 这样可以不修改state.posts的属性,而是直接返回新对象
          post._id === action.payload._id ? { ...post, likes:action.payload.likes} : post )
      }

最好把 State 对象设成只读。你没法改变它,要得到新的 State,唯一办法就是生成一个新对象。这样的好处是,任何时候,与某个 View 对应的 State 总是一个不变的对象。
利用**combineReducers()**可以产生一个整体的 Reducer 函数。该函数根据 State 的 key 去执行相应的子 Reducer,并将返回结果合并成一个大的 State 对象

React-Redux

它是redux作者封装的一个库,是一个第三方的模块,对Redux进一步的封装简化,提供了一些额外的API(例如:Provider,connect等),使用它可以更好的组织和管理我们的代码,遵循一定的组件拆分规范,在React中更方便的使用Redux

connect

connect()负责将UI组件(只是展示)与容器组件(只是状态管理)进行连接,
在UI组件内最后导出
export default connect(mapStateToProps, mapDispatchToProps)(UI组件)
connect()接受两个参数:mapStateToPropsmapDispatchToProps。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将state映射到 UI 组件的参数(props),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action
connect的两个参数都可以根据需求分别省略:
省略mapStateToProps,组件将不会监听 Redux store。UI 组件就不会订阅Store,但会更新Store,就是说Store的更新不会引起UI组件的更新
省略mapDispatchToProps,默认情况下dispatch会注入到你的组件props中,但只是订阅Store不涉及更新。

mapStateToProps

直白点的理解就是需要拿什么数据
mapStateToProps()作用就是像它的名字那样,建立一个从外部state对象到UI 组件的props对象的映射关系,写法如下

const mapStateToProps = state => ({
  profile: state.profile
})

上面的profile为UI组件内需要的数据名称,它们将会被挂载到props对象上,通过props.profile访问。state.profile即reducer函数返回的结果
mapStateToProps会订阅 Store,每当外部state更新时,就重新计算组件参数,触发组件重新render()
注意当外部state映射到props上后,又赋值给内部独立的state时,要在componentWillReceiveProps()中监听props的改变后,再将props上的数据通过setState更新状态
要注意componentWillReceiveProps未触发的原因可能是因为父组件未进行深拷贝

mapDispatchToProps

需要改什么数据
mapDispatchToProps可以是一个对象,也可以是一个函数(返回对象),用来建立 UI 组件的参数到store.dispatch方法的映射
如果mapDispatchToProps是一个函数,会得到dispatch和ownProps(容器组件的props对象)两个参数
如果mapDispatchToProps是一个对象,它的每个键名也是对应 UI 组件的同名参数,键值应该是一个函数

Provider

在app.js中使用Provider组件可以简洁的让子组件直接拿到state,其原理是context属性
在利用hooks代替redux时,也是利用context属性的原理传递state

redux-thunk

thunk为解决异步action而生
applyMiddleware是 Redux 的原生方法,作用是将所有中间件组成一个数组,依次执行
在app.js文件中进行配置后action.js中的方法就可以通过接收dispatch参数去发送异步的action

export const addPost = postData => dispatch => {
  axios.post("/api/posts", postData)
    .then(res =>
      dispatch({
        type: ADD_POST,
        payload: res.data
      })
    )
    .catch(err =>
      dispatch({
        type: GET_ERRORS,
        payload: err.response.data
      })
    )
}

action creator

Action creator的设计也是由Flux架构来的产物,它是一种辅助用的函数,用来创建Action的。但因为设计的不同,在Redux中的Action creator比在Flux更简单,它通常只用来返回Action对象而已,当然它本身是个函数,在返回前是可以再针对返回的动作数据先进行运算或整理的,例如像下面这样的函数
经过redux-devtool调试后,发现还是不对!!!最后只能通过dispatch去派发(dispatch嵌套dispatch也行),return不起作用
http://echizen.github.io/tech/2016/07-23-dispatch

1. 直接return
export function fetchPosts(reddit) {
  return {
    type: REQUEST_POSTS,
    reddit
  }
}
2. 利用dispatch
export function fetchPosts(reddit) {
  return dispatch => { // 函数柯里化写法
    return dispatch({ // dispatch返回值就是action,当然不return也行    
      type: REQUEST_POSTS,
      reddit
    })
  }
}

不懂可以看github,都有相应的注释~

相关标签: React系列 reactjs