【框架深入-React框架】react的状态以及状态管理

99 阅读7分钟

1.React哲学

1.1 将设计好UI划分为组件层级

这一步的主要工作有两个:组件划分组件命名

组件划分 单一功能原则,将一个组件当做一个功能和一个函数考虑 也就是说一个组件原则上只负责一个功能,如果让它负责多个功能,那就将他拆分成多个更小组件。 比如说一个展示的列表项,列表容器里边分为表头和表体,表体里面有有多个行,如果不同的行显示也不一样,那就要再细分。因为列表容器的功能是展示列表,表头可能会有按照不同的项的功能,表项是负责展示数据,不同的表项展示不同的数据。 thinking-in-react-components.png 组件命名 按照功能命名,组件名首字母一定要大写,不然会解释html的普通标签。 图片.png

1.2 用react创建一个静态界面

最好要将UI和交互分开,这是因为编写静态这是因为,编写一个应用的静态版本时,往往要编写大量代码,而不需要考虑太多交互细节;添加交互功能时则要考虑大量细节,而不需要编写太多代码

这一步的主要工作是如何干净的为组件添加样式和布局以及构建自己的组件库

构建自己的组件库 在创建组件的时候,我们会需要创建一些重用的组件,然后使用peops传入所需要的数据,当你的应用比较简单时,使用自上而下的方式更方便;对于较为大型的项目来说,自下而上地构建,并同时为低层组件编写测试是更加简单的方式。

干净的为组件添加样式和布局 或许我们会用到一些UI工具,比如, css modulessass lessant design

1.3 确定UI state的最小且完整表示

敲重点,找到合适最小且完整表示的state后续页面交互的时候,可以四两拨千斤,state一变,props全部都变,组件样式全部改变。

1. props和state的区别。

props(“properties” 的缩写)和 state 都是普通的 JavaScript 对象 。它们都是用来保存信息的,这些信息可以控制组件的渲染输出,而它们的一个重要的不同点就是:props 是传递给组件的(类似于函数的形参),而 stat e 是在组件内*被组件自己管理的(类似于在一个函数内声明的变量)。

2. setState()

state 就是一个普通的js对象,它不牛逼,牛逼的setState,执行setState()才会触发页面更新,然后根据react单向数据流的特点,state更新之后,相对应的props更新,进而产生交互,页面更新。对此setState做了优化来提升性能。

1. 为什么我setState的值不正确

function incrementCount(){
    setCount(count+1)
}
function incrementCount(){
   setCount((count)=>{
       return count+1;
   })
}
function handleSomething() {
   incrementCount();
   incrementCount();
   incrementCount();
   console.log(count)

}

上述代码如果调用的是第一个incrementCount() 执行三次之后还是1,但是如果调用的是第二个执行三次之后会变成3,并且二者都是触发生命周期更新函数一次,并且console.log(count)打印的永远都是更新之前的count给setState传递一个函数而不是一个对象,这样就可以保证每次调用都是最新版的state这是为什么呢?

setStae的异步更新机制: 因为setState的调用是分批进行,传递一个函数可以进行链式调用,确保一个她们一个是建立在另一个之上的。setState在事件处理函数内部是异步的,如果两个父子组件都有click事件,触发子组件,父组件也会触发,这种异步更新机制可以避免child被渲染两次,在大型应用中可以避免不必要的重新渲染来很好的提升性能。据我观察,如果一个事件处理函数内部出现异步代码,比如说需要通过promise发送网络请求,await等待请求结果,此时会触发批量更新,并且会触发声明周期的更新函数

为什么react不能立即更新state,而不对组件进行重新渲染呢? 官方回复,会破坏state和props的一致性,出现意想不到的bug。还会影响react新版本正在实现的新功能。

1.4 确定sate的存放位置

1.官方解决: 根据react的单项数据流的特性,所以将state存储在所有组件共同拥有者,如果没有就重新创建一个。

注意:React 中的数据流是单向的,并顺着组件层级从上往下传递。哪个组件应该拥有某个 state 这件事,对初学者来说往往是最难理解的部分。尽管这可能在一开始不是那么清晰,但你可以尝试通过以下步骤来判断: 对于应用中的每一个 state:
- 找到根据这个 state 进行渲染的所有组件。
- 找到他们的共同所有者(common owner)组件(在组件层级上高于所有需要该 state 的组件)。
- 该共同所有者组件或者比它层级更高的组件应该拥有该 state。
- 如果你找不到一个合适的位置来存放该 state,就可以直接创建一个新的组件来存放该 state,并将这一新组件置于高于共同所有者组件层级的位置。

2. Redux

随着 JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 state (状态) 。 这些 state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。

管理不断变化的 state 非常困难。如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依次地,可能会引起另一个 view 的变化。直至你搞不清楚到底发生了什么。state 在什么时候,由于什么原因,如何变化已然不受控制。 当系统变得错综复杂的时候,想重现问题或者添加新功能就会变得举步维艰。

这里的复杂性很大程度上来自于:我们总是将两个难以理清的概念混淆在一起:变化和异步。 我称它们为曼妥思和可乐。如果把二者分开,能做的很好,但混到一起,就变得一团糟。一些库如 React 试图在视图层禁止异步和直接操作 DOM 来解决这个问题。美中不足的是,React 依旧把处理 state 中数据的问题留给了你。Redux就是为了帮你解决这个问题。 图片.png

redux 三个核心概念:store、action、reducer。所有的状态存储在store中,action用来描述怎么修改store里面的状态,说白了就是方法和参数,就一个接口,手里有任务,自己不敢,得找人干,reducer是纯函数,就是干活的,为action中不同任务,有响应的解决方案,这个方案会修改state里面的内容。

但是 redux中这store,action,reducer是分开写的,不符合现在模块化开发、关注点分离的趋势,所以有没有一种新的方式,让我们开发的过程中更加注重业务逻辑的开发呢?于是它来了redux Toolkit,一个redux的工具包,用来简化redux的操作。