react 学习之路(记)- State:组件的记忆

State:组件的记忆

  1. 定义:组件通常需要更具交互更改屏幕上显示的内容,在 React 中,这种组件特有的记忆被称为 state。

  2. 背景:普通变量无法满足

  3. 原因:

    1. 局部变量无法在多次渲染中持久保存。react再次渲染组件是,它会从头开始渲–不会考虑之前对局部变量的任何更改。
    2. 更改局部变量不会触发渲染。React没有意识到它需要使用新数据再次渲染组件。
  4. 想要达到预期的效果:

    1. 保留,渲染之间的数据
    2. 触发 React 使用新数据渲染组件(重新渲染)
  5. 如何解决:
    useState Hook 提供了这两个功能

    1. State 变量用于保存渲染间的数据
    2. State setter 函数 更新变量并触发React 再次渲染组件。
  6. 使用:

	 ### 添加:
	 import { userState } from 'react' // 从文件顶部的React中导入 useState
	 ### 使用
	 const [thing, setThing] = useState(0)
	 // thing 是一个 state 变量, setThing 是对应的 setter 函数
	 // 这里的 [ 和 ] 语法称为数组结构。它允许你从数组中读取值。useState 返回的数组总是正好有两项 
	 // 惯例是将这对返回值命名为 const [thing, setThing]。你也可以将其命名为任何你喜欢的名称,但遵照约定俗成能使跨项目合作更易理解。
	 
	useState 的唯一参数是 state 变量的初始值。在这个例子中,thing 的初始值被useState(0)设置为 0。
	每次你的组件渲染时,useState 都会给你一个包含两个值的数组:
	state 变量 (thing) 会保存上次渲染的值。
	state setter 函数 (setThing) 可以更新 state 变量并触发 React 重新渲染组件。

  1. react - 第一个 Hook ( 英 [hʊk] 美 [hʊk] : 钩子 )

在 React 中,useState 以及任何其他以 ‘use’开头的函数 都被称为Hook
Hook 是特殊的函数,只在 React 渲染时有效

(ps:Hooks – 以 use 开头的函数 – 只能在组件或者自定义 Hook 的最顶层 调用。)

一个组件可以定义多个 state 变量
State 是隔离且私有的(state 完全私有于声明它的组件,父组件无法更改它。)

  1. 总结
  1. 当一个组件需要在多次渲染间“记住”某些信息时使用 state 变量。
  2. State 变量是通过调用 useState Hook 来声明的。
  3. Hook 是以 use 开头的特殊函数。它们能让你‘hook’到像 state 这样的React 特性中。
  4. Hook 可能会让你想起 import:它需要在非条件语句中调用。调用时,仅在组件顶层被调用才有效。
  5. useState Hook 返回一堆值:当前的 state 及 更新它的函数
  6. 你可以拥有多个 state 变量。在内部,React 按顺序匹配他们。
  7. State 是组件私有的。每个副本都有独属于自己的state。

文章参考:https://react.docschina.org/learn/state-a-components-memory

state 如同一张快照

–设置它不会更改你已有的 state 变量,但会触发重新渲染。

  1. 设置 state 会触发渲染
  2. 渲染会及时生成一张快照
  3. 随时间变化的 state

把一些列 state 更新 加入队列

  1. 设置 state 不会更改现有渲染中的变量,但会请求一次新的渲染。
  2. React 会在事件处理函数执行完成之后处理 state 更新。这被称为批处理。
  3. 要在一个事件中多次更新某些 state,你可以使用 setNumber(n => n + 1) 更新函数。

更新 state 中的对象

state 中可以保存任意类型的JavaScript值,包括对象
不应该直接修改保存在 React state中的对象。
更新对象时,需要创建一个新的对象,然后将state更新为此对象

  1. 什么事 mutation ?
    1. JS 中 不可变的:数字 字符串 布尔值 不可变(immutable),意味着不能被改变或是只读。更改时可以通过替换他们的值触发一次重新渲染。
    2. state 存放对象:
	const [position,setPosition] = useState({x:0,y:0});
	从技术上来讲,可以改变对象自身的内容。 这样做的时候,就知道了一个 mutation
	严格来说 React state 中存放的对象是可变的,但是最好像处理JS中那样视为不可变。修改时替换值。
  1. 将 state 视为只读(把所有存放在 state 中的 JavaScript 对象都视为只读的)
  2. 使用展开语法复制对象
 展开语法 ...xxx

只修改 first 参数
 const [thing,setThing] = useState({
		first:'23',
		second:'232',
		third:'2345'
	})
	// 第一种 
	setThing({
		first:'12',
		second:'232',
		third:'2345'
	})
	// 第二种 对象展开语法 ...
	setThing({
		...thing,// 复制 thing 中所有字段
		first:'12' // 但是覆盖 first 字段
	})
	!!!请注意 ... 展开语法本质是是“浅拷贝”——它只会复制一层。这使得它的执行速度很快,但是也意味着当你想要更新一个嵌套属性时,你必须得多次使用展开语法。
	

更新一个嵌套对象

const [thing,setThing] = useState({
	first:'1',
	seconds:{
		secFirst:'21',
		secSecond:'22',
		secThird:'23'
	}
})

setThing({
	...thing,
	seconds:{
		...thing.seconds,
		secSecond:'24'
	}
})

使用 Immer 编写简洁的更新逻辑

  1. 扁平化
  2. immer 是一个非常流行的库
updateThing(draft =>{
	draft.seconds.secSecond = '24'
})

※ Immer 如何运行
> 由 Immer 提供的 draft 是一种特殊类型的对象,被称为 Proxy,
> 它会记录你用它所进行的操作。这就是你能够随心所欲地直接修改对象的原因所在!
> 从原理上说,Immer 会弄清楚 draft 对象的哪些部分被改变了,
> 并会依照你的修改创建出一个全新的对象。

  1. 总结

将 React 中所有的 state 都视为不可直接修改的。
当你在 state 中存放对象时,直接修改对象并不会触发重渲染,并会改变前一次渲染“快照”中 state 的值。
不要直接修改一个对象,而要为它创建一个 新 版本,并通过把 state 设置成这个新版本来触发重新渲染。
你可以使用这样的 {…obj, something: ‘newValue’} 对象展开语法来创建对象的拷贝。
对象的展开语法是浅层的:它的复制深度只有一层。
想要更新嵌套对象,你需要从你更新的位置开始自底向上为每一层都创建新的拷贝。
想要减少重复的拷贝代码,可以使用 Immer。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值