上饶做网站最好的公司,广州市建筑工程有限公司,常德地区网站建设,上海网站备案网站useState
让页面“动”起来
例如实现一个 click 计数功能#xff0c;普通变量无法实现。即#xff1a;修改普通变量无法触发组件的更新 rerender
通过 useState 即可实现。
state 是什么
State, A component’s memory —— 这个比喻非常好#xff01;
props 父组件传…useState
让页面“动”起来
例如实现一个 click 计数功能普通变量无法实现。即修改普通变量无法触发组件的更新 rerender
通过 useState 即可实现。
state 是什么
State, A component’s memory —— 这个比喻非常好
props 父组件传递过来的信息state 组件自己内部的状态不对外
每次 state 变化都会触发组件更新从新渲染页面。
代码演示参考 react-ts-demo 中 pages/StateDemo1.tsx
import React, { FC, useState } from reactconst Demo: FC () {// let count 0 // 普通的 js 变量无法触发组件的更新const [count, setCount] useState(0) // useState 可以触发组件的更新// const [name, setName] useState(双越)function add() {// count// setCount(count 1)setCount(count count 1) // 使用函数state 更新不会被合并setCount(count count 1)setCount(count count 1)setCount(count count 1)setCount(count count 1)// setCount(count count 1)console.log(cur count , count) // 异步更新无法直接拿到最新的 state 值}return (divbutton onClick{add}add {count}/button/div)
}export default Demo
state 的特点
异步更新
代码演示
PSsetState 传入函数可同步更新
可能会被合并
代码演示
不可变数据
state 可以是任意 JS 类型不仅仅是值类型。 不可直接修改 state 而要 setState 新值。
代码演示
PS函数组件每个更新函数从新执行state 被重置而不是被修改。state 可以理解为 readOnly
immer
Immer 简化了不可变数据结构的处理。特别是对于 JS 语法没那么熟悉的人。
代码演示参考 react-ts-demo 中 pages/ImmerDemo1.tsx
import React, { FC, useState } from react
import produce from immerconst Demo: FC () {// const [userInfo, setUserInfo] useState({ name: 柚子, age: 20 })// function changeAge() {// // // **不可变数据** - 不去修改 state 的值而是要传入一个新的值 —— 重要// // setUserInfo({// // ...userInfo,// // age: 21,// // })// setUserInfo(// produce(draft {// draft.age 21// })// )// }const [list, setList] useState([x, y])function addItem() {// // **不可变数据** - 不去修改 state 的值而是要传入一个新的值 —— 重要// setList(list.concat(z))// // setList([...list, z])setList(produce(draft {draft.push(z)}))}return (divh2state 不可变数据/h2{/* div{JSON.stringify(userInfo)}/divbutton onClick{changeAge}change age/button */}div{JSON.stringify(list)}/divbutton onClick{addItem}add item/button/div)
}export default Demo
实战List 页面使用 state
使用 state使用 immer push修改 isPublish
代码参考 pages/List2.tsx
import React, { FC, useState, useEffect } from react
import produce from immer
import QuestionCard from ./components/QuestionCard// 组件是一个函数执行返回 JSX 片段组件初次渲染执行这个函数
// 任何 state 更新都会触发组件的更新重新执行函数
const List2: FC () {useEffect(() {console.log(加载 ajax 网络请求)return () {console.log(销毁)}}, []) // 无依赖组件初次渲染时执行// const [count, setCount] useState(0)const [questionList, setQuestionList] useState([{ id: q1, title: 问卷1, isPublished: false },{ id: q2, title: 问卷2, isPublished: true },{ id: q3, title: 问卷3, isPublished: false },{ id: q4, title: 问卷4, isPublished: true },])// useEffect(() {// console.log(question list changed)// }, [questionList])// useEffect(() {// console.log(count changed)// }, [count, questionList])function add() {// setCount(count 1)const r Math.random().toString().slice(-3)// setQuestionList(// // 新增 concat// questionList.concat({// id: q r,// title: 问卷 r,// isPublished: false,// })// )// immer 的方式setQuestionList(produce(draft {draft.push({id: q r,title: 问卷 r,isPublished: false,})}))}function deleteQuestion(id: string) {// // 不可变数据// setQuestionList(// // 删除 filter// questionList.filter(q {// if (q.id id) return false// else return true// })// )// immer 的方式setQuestionList(produce(draft {const index draft.findIndex(q q.id id)draft.splice(index, 1)}))}function publishQuestion(id: string) {// setQuestionList(// // 修改 map// questionList.map(q {// if (q.id ! id) return q// return {// ...q,// isPublished: true,// }// })// )// immer 的方式setQuestionList(produce(draft {const q draft.find(item item.id id)if (q) q.isPublished true}))}return (divh1问卷列表页2/h1div{questionList.map(question {const { id, title, isPublished } questionreturn (QuestionCardkey{id}id{id}title{title}isPublished{isPublished}deleteQuestion{deleteQuestion}publishQuestion{publishQuestion}/)})}/divdivbutton onClick{add}新增问卷/button/div/div)
}export default List2 代码参考 /components/QuestionCard
import React, { FC, useEffect } from react
import classnames from classnames
// import ./QuestionCard.css
import styles from ./QuestionCard.module.scss// ts 自定义类型
type PropsType {id: stringtitle: stringisPublished: booleandeleteQuestion?: (id: string) voidpublishQuestion?: (id: string) void
}// FC - functional component
const QuestionCard: FCPropsType props {const { id, title, isPublished, deleteQuestion, publishQuestion } propsfunction publish(id: string) {publishQuestion publishQuestion(id)}function del(id: string) {deleteQuestion deleteQuestion(id)}// useEffect(() {// console.log(question card mounted)// return () {// console.log(question card unmounted, id) // 销毁// }// // 生命周期创建更新state 变化销毁// }, [])// let itemClassName list-item// if (isPublished) itemClassName published// // 逻辑稍微复杂// const itemClassName classnames(list-item, { published: isPublished })// const itemClassName classnames({// list-item: true,// published: isPublished,// })const listItemClass styles[list-item]const publishedClass styles.publishedconst itemClassName classnames({[listItemClass]: true,[publishedClass]: isPublished,})return (div key{id} className{itemClassName}strong{title}/strongnbsp;{/* 条件判断 */}{isPublished ? span className{styles[published-span]}已发布/span : span未发布/span}nbsp;buttononClick{() {publish(id)}}发布问卷/buttonnbsp;buttononClick{() {del(id)}}删除问卷/button/div)
}export default QuestionCard
最重要的就是不可变数据 —— 这是 React state 的核心