State
在React中,什么是state?
在 React 中,随时间变化的数据被称为状态(state)。你可以向任何组件添加状态,并按需进行更新。
如何添加使用state?
- 点击获取教程代码
- 关于此框架–More docs
使用 useState Hook 为组件添加状态
例如
import { useState } from 'react';
const [index, setIndex] = useState(0);
const [showMore, setShowMore] = useState(false);
state特别之处
新的(奇怪的)知识要增加了~ 下面会做解释哦~
- 与普通 JavaScript 变量不同,React state的行为更像一个快照。设置它并不改变你已有的状态变量,而是触发一次重新渲染。
- 通俗来说,就是临时的,一次性的那种,第一次看到这个说实话我也很惊讶
- 官方文档是这么解释的:React 这样工作是为了帮助你避免微妙的 bug。
举个栗子
console.log(count); // 0
setCount(count + 1); // 请求用 1 重新渲染
console.log(count); // 仍然是 0!
为什么出现这个问题?如何解决这个问题?
原因:一个 state 变量的值在 React 通过调用你的组件“获取 UI 的快照”时就被“固定”了, 即使其事件处理函数的代码是异步的。
解决:set的时候传入函数就OK了,举例如下
setScore(s => s + 1)
更新 state 后替换 state ,会如何运行呢?
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 5);
setNumber(n => n + 1);
setNumber(42);
}}>增加数字</button>
</>
)
}
答案如下:
注意事项
- 在严格模式下,React 会执行每个更新函数两次(但是丢弃第二个结果)以便帮助你发现错误。
useState Hook 功能
- 在 React 中,useState 以及任何其他以“use”开头的函数都被称为 Hook。
- State 变量 用于保存渲染间的数据。
- State setter 函数 更新变量并触发 React 再次渲染组件。
- 渲染同一个组件两次,每个副本都会有完全隔离的 state,改变其中一个不会影响另一个。
用法
对于下面代码来说:index 是一个 state 变量,setIndex 是对应的 setter 函数。
import { useState } from 'react';
const [index, setIndex] = useState(0);
使用state 处理对象和数组的数据变化
- 创建一个新的对象(或复制现有的对象),然后用这个副本来更新状态
- 使用 … 展开语法来复制你想改变的对象和数组
举个栗子
import { useState } from 'react';
export default function Form() {
const [person, setPerson] = useState({
name: 'Niki de Saint Phalle',
artwork: {
title: 'Blue Nana',
city: 'Hamburg',
image: 'https://i.imgur.com/Sd1AgUOm.jpg',
}
});
function handleNameChange(e) {
setPerson({
...person,
name: e.target.value
});
}
function handleTitleChange(e) {
setPerson({
...person,
artwork: {
...person.artwork,
title: e.target.value
}
});
}
function handleCityChange(e) {
setPerson({
...person,
artwork: {
...person.artwork,
city: e.target.value
}
});
}
function handleImageChange(e) {
setPerson({
...person,
artwork: {
...person.artwork,
image: e.target.value
}
});
}
return (
<>
<label>
Name:
<input
value={person.name}
onChange={handleNameChange}
/>
</label>
<label>
Title:
<input
value={person.artwork.title}
onChange={handleTitleChange}
/>
</label>
<label>
City:
<input
value={person.artwork.city}
onChange={handleCityChange}
/>
</label>
<label>
Image:
<input
value={person.artwork.image}
onChange={handleImageChange}
/>
</label>
<p>
<i>{person.artwork.title}</i>
{' by '}
{person.name}
<br />
(located in {person.artwork.city})
</p>
<img
src={person.artwork.image}
alt={person.artwork.title}
/>
</>
);
}
试一把这个代码吧~~
Tips: 可以使用 Immer 之类的库来减少重复代码
import { useImmer } from 'use-immer';
export default function Form() {
const [person, updatePerson] = useImmer({
name: 'Niki de Saint Phalle',
artwork: {
title: 'Blue Nana',
city: 'Hamburg',
image: 'https://i.imgur.com/Sd1AgUOm.jpg',
}
});
function handleNameChange(e) {
updatePerson(draft => {
draft.name = e.target.value;
});
}
function handleTitleChange(e) {
updatePerson(draft => {
draft.artwork.title = e.target.value;
});
}
function handleCityChange(e) {
updatePerson(draft => {
draft.artwork.city = e.target.value;
});
}
function handleImageChange(e) {
updatePerson(draft => {
draft.artwork.image = e.target.value;
});
}
return (
<>
<label>
Name:
<input
value={person.name}
onChange={handleNameChange}
/>
</label>
<label>
Title:
<input
value={person.artwork.title}
onChange={handleTitleChange}
/>
</label>
<label>
City:
<input
value={person.artwork.city}
onChange={handleCityChange}
/>
</label>
<label>
Image:
<input
value={person.artwork.image}
onChange={handleImageChange}
/>
</label>
<p>
<i>{person.artwork.title}</i>
{' by '}
{person.name}
<br />
(located in {person.artwork.city})
</p>
<img
src={person.artwork.image}
alt={person.artwork.title}
/>
</>
);
}
Immer处理数组
import { useState } from 'react';
import { useImmer } from 'use-immer';
let nextId = 3;
const initialList = [
{ id: 0, title: 'Big Bellies', seen: false },
{ id: 1, title: 'Lunar Landscape', seen: false },
{ id: 2, title: 'Terracotta Army', seen: true },
];
export default function BucketList() {
const [list, updateList] = useImmer(initialList);
function handleToggle(artworkId, nextSeen) {
updateList(draft => {
const artwork = draft.find(a =>
a.id === artworkId
);
artwork.seen = nextSeen;
});
}
return (
<>
<h1>Art Bucket List</h1>
<h2>My list of art to see:</h2>
<ItemList
artworks={list}
onToggle={handleToggle} />
</>
);
}
function ItemList({ artworks, onToggle }) {
return (
<ul>
{artworks.map(artwork => (
<li key={artwork.id}>
<label>
<input
type="checkbox"
checked={artwork.seen}
onChange={e => {
onToggle(
artwork.id,
e.target.checked
);
}}
/>
{artwork.title}
</label>
</li>
))}
</ul>
);
}
小伙伴们,先写到这里啦,我们明天再见啦~~
大家要天天开心哦
欢迎大家指出文章需要改正之处~
学无止境,合作共赢