深入浅出 React&Redux 笔记

date
Jun 11, 2019
slug
react-redux-note
status
Published
tags
Reactjs
summary
react、redux学习笔记,包括目录组织、state变化、组件创建等
type
Post

知识点总结

  1. 高内聚(js、jsx、css) 低耦合(弱化不同组件间的关系)
  1. react组件数据
    1. 生命周期 (执行顺序如序号顺序)
        • 装载过程
            1. constructor (初始化state,绑定this。当然也可以不绑定,在class中使用声明变量&尖头函数的写法)
            1. getlnitialState (React.createClass中使用)
            1. getDefaultProps (React.createClass中使用)
            1. componentWillMount (这个时候没有任何渲染出来的结果,即使调用this.setState 修改状态也不会引发重新绘制换句话说,所有可以在这个 component­WillMount 中做的事情,都可以提前到 constructor 中间去做)
            1. render (完全根据 this.state 和 this.props 来决定返回的结果,而且不要产生任何副作用。在 render 函数中去调用 this.setState 毫无疑问是错误的,因为一个纯函数不应该引起状态的改变)
            1. componentDidMount (组件已经被装载到 DOM 树上了,这个时候我们可以通过请求来填充组件的内容、使用三方代码获取dom, 需要注意的是该生命周期不会在一个render后立即执行,而是在所有子组件render结束后执行,这是因为render只返回jsx对象并不往dom树上装载内容,具体的内容装载是react经过vm后才决定的)
        • 更新过程
            1. shouldComponentUpdate (如果这个函数返回 true,那就会继续更新过程,接下来调用 render 函数;反之,如果得到 一个 false,那就立刻停止更新过程,也就不会引发后续的渲染了)
            1. componentWillReceiveProps (只要是父组件的 render 函数被调用,在 render 函数里面被谊染的子组件就会经历更新过程,不管父组件传给子组件的 props 有没有改变,都会触发子组件的 componentWillReceiveProps 函数, 子组件中的 setstate 不会调用该方法)
            1. componentWillUpdate
            1. render
            1. componentDidUpdate
        • 卸载过程
            1. componentWillUnmount (通常解绑事件、定时器等)
    2. propTypes 建议在开发环境可加,生产环境通过babel-react-optimize去掉
    3. 初始化state:this.state = { count: props.initValue || 0 }this.state = { count: props.initValue }; xxx.defaultProps = { count: 0 }
    4. prop&state的对比:
        • prop 用于定义外部接口, state 用于记录内部状态;
        • prop 的赋值在外部世界使用组件时, state 的赋值在组件内部;
        • 组件绝不应该改变 prop 的值(要严格遵守单向数据流原则,保证 ui=render(data) 这个函数无任何副作用),而 state存在的目的就是让组件来改变的 。
  1. 模块化
用 React和 Redux来构建前端网页应用,这两者都奉 行这样一个公式 UI=render(state) 来产生用户界面。 React才适合于视图层面的东西,但是不能指望靠React来管理应用的状态, Redux才适合担当应用状态的管理工作。
  • 从架构出发,当我们开始一个新的应用的时候,有几件事情是一定要考虑清楚的:
      1. 代码文件的组织结构
        1. 按角色组织:
          1. reducers/
            	todoReducer.js
            	filterReducer.js
            actions/ 
            	todoActions.js
            	filterActions.js
            components/
            	todoList.js
            	todoItem.js
            	filter.js
            containers/
            	todoListContainer.js
            	todoiternContainer.js
            	filterContainer.js
                            
            // 唯一的缺点是新增功能需要在不同的文件夹下切换并且创建新文件
        2. 按功能组织
          1. todoList/
            	actions.js
            	actionTypes.js
            	index.js
            	reducer.js
            	views/
            		component.js
            		container.js
            filter/
            	actions.js
            	actionTypes.js
            	index.js
            	reducer.js
            	views/
            		component.js
            		container.js
      1. 模块接口
        1. 常规导入:
          1. import * as actions from ’ .. /todoList/actions ’;
            import container as TodoList from ’../todoList/views/container’;
            
            // 这种写法当然能够完成功能,但是却非常不合理,因为这让 filter模块依赖于 todoList模块的内部结构,而且直接伸手到 todoList 内部去导人想要的部分
        2. 统一入口导入 (index.js)
          1. import * as actions from ’. /actions.js ’;
            import reducer from ’. /reducer.js’;
            import view from ’./views/container.js ’;
            
            export {actions, reducer, view};
            
            // 使用如下
            
            import {actions , reducer, view as TodoList} from ’../todoList’
        3. Store 的状态树设计
            • 一个模块控制一个状态节点
            • 避免冗余数据 (数据一致性)
            • 树形结构扁平,避免出现以下情况:
              • const d = state.A && state.A.B && state.A.B.C && state.A.B.C.D;
  1. 组件性能优化
    1. 容器组件与傻瓜组件 (让一个组件只专注做一件事,容器组件进行数据处理然后将数据传入傻瓜组件,傻瓜组件只负责渲染)
    2. 使用 shouldcomponentupdate 来避免不必要的组件更新(重新渲染)
    3. 那么如何查看 chrome 中 react 性能表现?参考资料如下:
  1. redux
    1. redux基本原则:
        • 唯一数据源(Single Source ofTruth)
        • 保持状态只读( State is read-only)
        • 数据改变只能通过纯函数完成( Changes are made with pure functions)
    2. 保持数据的唯一性 (context & react-redux)
    3. react-redux 两个最主要功能:
        • connect: 连接容器组件和傻瓜组件;
        • Provider: 提供包含 store 的 context (context 完全可以实现 provider 但是 react-redux 中的 provider 包含三个函数:subscribe、dispatch、getState。react-redux 定义了 Provider 的 componentWillReceiveProps 函数,在 React组件的生命周期中, componentWillReceiveProps 函数在每次重新渲染时都会调用到,react­ redux 在 componentWillReceiveProps 函数中会检查这一次渲染时代表 store 的 prop 和上 一次的是否一样。 如果不一样,就会给出警告,这样做是为了避免多次渲染用了不同的 Redux Store。 每个 Redux 应用只能有一个 Redux Store,在整个 Redux 的生命周期中都应该保持 Store 的唯一性)
  1. 高阶组件
特点
区别
操纵 prop / 访问 ref / 抽取状态 / 包装组件
新组件、参数组件都要经历各自的生命周期
操纵 prop / 操纵生命周期函数
只有一个生命周期(super.render())

提示

  1. 在 jsx 用直接把匿名函数赋值的方法,看起来非常简洁而且方便,其实并不是值得提倡的方法。因为每次渲染都会创造一个新的匿名方法对象 ,而且有可能引发子组件不必要的重新渲染。
  1. render 和 shouldComponentUpdate 函数,也是 React 生命周期函数中唯二两个要求有返回结果的函数。 render 函数的返回结果将用于构造 DOM 对象,而 shouldComponent­Update 函数返回一个布尔值,告诉 React 库这个组件在这次更新过程中是否要继续。
  1. 为什么 react 中大多数的调用通常是闭包形式的多层调用? 因为遵从一个函数只做一件事的原则connect(mapStateToProps, mapDispatchToProps)(Counter)
    1. /** 这是 thunk 的源码实现,只是单纯的判断了 action 类型,具体做了如下操作:
       * 1. 调用 dispatch派发出一个新 action对象;
       * 2. 调用 getState获得当前ReduxStore上的状态;
       * 3. 调用next告诉Redux当前中间件工作完毕,让Redux调用下一个中间件;
       * 4. 访问 action对象 action上的所有数据;
       */
      function createThunkMiddleware(extraArgument) {
          return ({ dispatch, getState }) => next => action=> {
              if (typeof action === "function"){
                  return action(dispatch , getState , extraArgument);
              }
              return next(action)
          }
      }
  1. 触发 re-render 的方式:
    1. setState
    2. props 改变
    3. forceupdate(change Key)
  1. fetch认为只要服务器返回一个合法的 HTTP 响应就算成功,就会调用 then提供的回调函数,即使这个HTTP响应的状态码是表示出错了的400或者500。因为 fetch 的这个特点,所以我们在 then 中,要做的第一件事就是检查传人参数 response status 字段,只有 status 是代表成功的 200 的时候才继续,否则以错误处理 。
  1. 组件 ⇒ action ⇒ store ⇒ reducers 关系图:
    1. notion image
 

© i7eo 2017 - 2022