这种情况下如果用
setState({…})
这种形式的话修改数据的话会比较麻烦,所以推荐函数式写法:
this.setState(state => {
state.people[2].englishName = 'Robin Lee'
return {...state}
});
函数式setState写法要求每次都返回一个新的引用,在类组件走遍天下的那个时代,state这个变量几乎存储了此组件中的所有数据,便于集中访问与管理。
用了函数式组件定义数据就不能再这么定义了,假如你要是还像以前一样那么写:
const [state, setState] = useState({
people: [
name: '马云',
englishName: 'Jack Ma'
name: '马化腾',
englishName: 'Pony Ma'
name: '李彦宏',
englishName: 'Robin Li'
});
那么你的setState就不太好改了,相信用过React Hooks的小伙伴们都能懂,而且这也不是被推荐的写法,一般来说我们会尽可能的细分:
const [jack, setJack] = useState({
name: '马云',
englishName: 'Jack Ma'
});
const [pony, setPony] = useState({
name: '马化腾',
englishName: 'Pony Ma''
});
const [robin, setRobin] = useState({
name: '李彦宏',
englishName: 'Robin Li'
});
这样的话修改数据就方便多了,粒度也更细腻,但是就是写起来麻烦、不够直观、代码量也更多,尤其是当你的数据量比较大、或者嵌套层级比较深的情况下那简直就是一场灾难。
那么怎么样才能既像以前setState那样方便快捷,同时又能使用函数式组件呢?聪明的朋友们应该猜也猜到了:useImmer!
来看看useImmer是怎么撰写上述逻辑的:
const [state, setState] = useImmer({
people: [
name: '马云',
englishName: 'Jack Ma'
name: '马化腾',
englishName: 'Pony Ma'
name: '李彦宏',
englishName: 'Robin Li'
setState(state => {state.people[2].name = 'Robin Lee'})
无论嵌套层级多么深,无论数据有多么复杂,useImmer总能让你找到当年 this.setState(state => state.people[2].name = ‘Robin Lee’) 的感觉,但是不同之处除了一个要用 this. 而另一个不用以外还有一个需要注意的地方:
原生的setState直接可以当作返回值,而这个useImmer生成的盗版useState修改后的值不能被直接当作返回值返回,所以需要在函数体外面有大括号。
当然也可以自定义返回值,返回什么值就会更新成什么值。
喜欢我文章的朋友记得关注+点赞啊!
$ yarn add use-state-as-array
import useStateAsArray from 'use-state-as-array' ;
const [ stateAsArray , setStateAsArray ] = useStateAsArray ( [ 'first' , 'second' ] )
setStateAsArray ( 0 , 'new value' )
useImmer
useImmer(initialState)与非常相似。 该函数返回一个元组,该元组的第一个值是当前状态,第二个是更新程序功能,该功能接受一个或一个值作为参数。
使用沉浸式生成器功能管理状态
将函数传递给更新程序时,可以自由更改draft参数,直到生产者结束并且更改将变为不可变并成为下一个状态。
示例: :
import React from "react" ;
import { useImmer } from "use-immer" ;
function App ( ) {
const [ person , updatePerson ] = useImmer ( {
name : "Michel" ,
age : 3
如果一次重新渲染导致某些依赖项发生了改变,或你没有提供这个参数列表,你的函数 createHandle 将会被重新执行,而新生成的句柄则会被分配给 ref。参数一:计算要缓存的值的函数。同样,并不是所有的记忆都是有效的:一个“总是新的”的值就足以破坏整个组件的记忆。一般来说,我们最好是在真实环境中测试组件,但对于复杂的状态更新逻辑,针对特定的初始状态和 action,断言 reducer 返回的特定状态会很有帮助。如果有足够的空间,工具提示应该出现在元素的上方,但如果它不合适,它应该出现在元素的下方。
import React, { useState, useEffect, useReducer } from 'react';import { useImmer } from "use-immer"import './App.css';function reducer(state: { count: number; }, action: { type: any; }) {switch (actio...
react hooks 是 React 16.8 的新增特性。 它可以让我们在函数组件中使用 state 、生命周期以及其他 react特性,而不仅限于 class 组件。react hooks 的出现,标示着 react中不会在存在无状态组件了,只有类组件和函数组件。具体可查看官网。
函数组件不能使用state,遇到交互更改状态等复杂逻辑时不能更好地支持,hooks让函数组件更靠近class组件,拥抱函数式编程。
解决副作⽤问题,hooks出现可以处理数据获取、订阅、定时执行任务、手动修
useReducer 是 useState 的替代品,它可以更好的管理组件的状态。
useReudcer 的格式:
import { useReducer } from "react";
let [state, dispatch] = useReducer(reducer, initialArg, init);
各个变量的含义:
state 拿到状态数据;
dispatch 派发 action 的函数;
reducer 我们自己编写的 reducer 函数;
在 React 中使用 Immer 管理不可变状态
在 React 中,使用不可变状态可以快速且高效地比较更改前后的状态树。因此,每个组件可在执行任何成本很高的 DOM 操作之前,决定是否重新渲染。
我希望你已经知道:
javaScript 是可变的,我们必须自己实现不可变性。
像 Redux 这样流行的状态管理库也遵循着相同的理念。当我们使用 reducers(译者注:根级的 reduce 函数 reducer 拆分为多个 reducers)时,它期望我们不要改变状态,以避免产生任何的副作用。但是,对
不可变数据
React的老手们早就知道为什么要用不可变数据了,但是为了防止新手们看不懂,所以还是要解释一下什么是不可变数据,不可变数据指的其实就是当你修改一个数据的时候,这个数据会给你返回一个新的引用,而自己的引用保持不变,有点像是经常用到的数组的map方法:
const arr1 = [1, 2, 3];
const arr2 = arr1.map(item => item * 10);
动手点关注干货不迷路useStateuseState 可以说是我们日常最常用的 hook 之一了,在实际使用过程中,有一些简单的小技巧能帮助你提升性能 & 减少出 bug 的概率。使用 惰性初始值(https://reactjs.org/docs/hooks-reference.html#lazy-initial-state)通常我们会使用以下的方式初始化 state。const[st...
hook都是一些以use开头的函数,表示钩子React 官网提供了 些内置的 hook:ruseState、 useEffect、useMemo、useCallback…允许自定义 hookhook使用规则:只能用于函数组件函数组件中使用自定义hook中使用需要在函数组件的顶层调用,不能在if、for、嵌套中使用需要以use开头。
背景本文旨在分享,React hook 在中大型中台项目中的实践,适合熟悉 React hook 用法的同学,希望能对你有帮助。用到的库1. unstated-next200 bytes to never think about React state management libraries ever again.永远不必再考虑 React 状态管理了,仅仅 200 字节的状态管理解决...