赞
踩
在编写页面时,我们需要将后端传过来的数据显示到指定页面上。自然而然我们可以想到可以用多个变量保存数据,然后放到页面指定位置显示数据。那问题来了,这些“状态”变量值保存呢?
有的小伙伴可能会说,可以用 var 、const 、let 来定义变量。是的,它们确实可以定义变量,但是随之又会有新的问题出现–变量改变后,我们想让页面重新渲染,显然它们是做不到的!
所以这次"主角"-- useState 出现了。
我可以简单认为 useState 可以定义变量,且这些变量改变后,页面也会随之重新渲染。
好了,进入正题。
const [state, setState] = useState(initialState);
useState 返回一个长度为2的数组。大部分我们是这样定义属性值变量的。如下
const [key, setKey] = useState(0);
useState 既然返回的是一个数组,我们可以这样写:
const keyArr = useState(0);
const key = keyArr[0]; // 变量
const setKey = keyArr[1]; // 改变变量的函数
这种写法显然太麻烦了,所以也很少有人用。之所以聊这中写法,其实想让小伙伴理解 useState 的返回值的类型。
如果还有对 ES6 解构赋值不太了解的小伙伴,可以去 传送门
举例说明
import { useState } from 'react'; const Counter = () => { const [count, setCount] = useState(0); // 方法一 function handleClick() { setCount(count + 1); } // 方法二 function handleClickFn() { setCount((prevCount) => { return prevCount + 1; }); } return ( <> Count: {count} <button onClick={handleClick}>+</button> <button onClick={handleClickFn}>+</button> </> ); } export default Counter;
我们通过 useState 定义了一个状态值变量:count,其初始值为:0
同时,还定义了一个用于改变 count 变量的函数:setCount
假如,我们想利用先前的 count 来计算(count + 1)新的 count 值,我们有两种方法实现,如上。
正常情况下,这两种方法没什么区别,都能改变变量的值,让页面重新渲染。
其实,这两种方法还是有点区别的,这也是前端面试经常问到的。如下
import { useState } from 'react'; const Counter = () => { const [count, setCount] = useState(0); // 方法一 function handleClick() { setCount(count + 1); setCount(count + 1); } // 方法二 function handleClickFn() { setCount((prevCount) => { return prevCount + 1; }); setCount((prevCount) => { return prevCount + 1; }); } return ( <> Count: {count} <button onClick={handleClick}>Click</button> <button onClick={handleClickFn}>ClickFn</button> </> ); } export default Counter;
当我们点击 Click 按钮时,发现 count 每次只增加 1;
当我们点击 ClickFn 按钮时,发现 count 每次却增加 2;
这是因为当我们使用一个新的 state 更新 count 值,如果多次频繁调用 useState,react 为了提高性能,它将多次 setCount 合并为最后一次调用。所以,点击 Click 按钮时,count 每次只增加 1;
当我们使用函数式方法更新 state时,因为形参 preCount 永远拿到的都是最新的 count 值,而且它也不会将多次 setCount 合并调用。所以,点击 ClickFn 按钮时,count 每次增加 2;
如果你想定义多个变量,可以:
const [count, setCount] = useState(0);
const [value, setValue] = useState("你好,世界!");
const [visible, setVisible] = useState(false);
如果变量过多,我们也可以自定义 Hook – useSetState
/** * 自定义Hook--useSetState * @description 用法和Class组件的setState()类似 */ import { useCallback, useState } from 'react'; const useSetState = ( initialState = {}, )=> { const [state, setState] = useState(initialState); const setMergeState = useCallback((patch) => { setState((prevState) => ({ ...prevState, ...(typeof patch === "function" ? patch(prevState) : patch), })); }, []); return [state, setMergeState]; }; export default useSetState;
我们知道 useState 的形参 initialState 可以是的 字符串、数组、布尔值…类型,当它是一个函数时,在每次状态值或者属性值发生改变时,函数里的代码是否也会重新执行?
const [state, setState] = useState(initialState);
const Counter = () => {
const [count, setCount] = useState(() => {
const obj = JSON.parse(bigJsonData); // 昂贵操作
return obj.count;
});
...
}
答案是肯定不会重新执行的。
每当 React 重新渲染组件时,都会执行useState(initialState)。如果初始状态是(数字,布尔值等),则不会有性能问题。
当初始状态需要昂贵的性能方面的操作时,可以通过为useState(functionCallback)提供一个函数来返回初始值,functionCallback 仅会在初次渲染时执行,在后续的渲染将不会再执行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。