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