反应JS |使用状态钩子
函数式组件是 ReactJS 中一些比较常用的组件。大多数开发人员更喜欢使用功能组件而不是基于类的组件,原因很简单,功能组件需要较少的编码(在开发人员方面)。但是,当与功能组件一起使用时,该类的两个主要功能会丢失 - 通过渲染调用持续存在的专用状态以及使用生命周期函数来控制组件在其生命周期的不同阶段的外观和行为。
从 16.8 版本开始,ReactJS 中添加了一个名为 hooks 的新特性,它暴露了基于类的组件的各种特性。两个最常用的钩子是 useState() 钩子,它允许函数式组件拥有自己的专用状态,以及 useEffect() 钩子,它允许函数式组件在每次渲染之前操作 DOM 元素(几乎就像一个人可以做的那样)它在生命周期函数中)。
useState() 钩子允许在函数内声明状态变量。需要注意的是,useState() 的一次使用只能用于声明一个状态变量。
示例:演示 useState() 钩子的基本用法的程序。
文件名- App.js:创建一个 React 应用程序并将 src 文件夹中的App.js文件编辑为:
javascript
import React, { useState } from 'react';
function App() {
const click = useState('GeeksForGeeks');
return (
Welcome to {click}
);
}
export default App;
javascript
import React, { useState } from 'react';
function App() {
const [click, setClick] = useState(0);
// using array destructuring here
// to assign initial value 0
// to click and a reference to the function
// that updates click to setClick
return (
You clicked {click} times
);
}
export default App;
javascript
import React, { useState } from 'react';
function App() {
const [click, setClick] = useState(0);
return (
You've clicked {click} times!
The number of times you have clicked
is {click%2==0?'even!':'odd!'}
);
}
export default App;
javascript
import React, { useState } from 'react';
function App() {
const [click, setClick] = useState([]);
const addNumber = () => {
setClick([
...click,
{
id: click.length,
value: Math.random() * 10
}
]);
};
return (
{click.map(item => (
- {item.value}
))}
);
}
export default App;
javascript
import React, { useState } from 'react';
function App() {
const [data, setData] = useState({
username: '',
password: ''
});
const [form, setForm] = useState({
username: '',
password: ''
});
const [submit, submitted] = useState(false);
const printValues = e => {
e.preventDefault();
setForm({
username: data.username,
password: data.password
});
submitted(true);
};
const updateField = e => {
setData({
...data,
[e.target.name]: e.target.value
});
};
return (
{submit?form.username:null}
{submit?form.password:null}
);
}
export default App;
输出:
useState() 返回的值由一个包含两个值的数组组成。第一个值是状态变量的初始(或起始)值,而第二个值是对可用于更新变量的函数的引用。人们总是可以使用数组解构来一次分配两个值,以便它们可以在组件中使用。当然,它们也可以通过使用 useState() 分配变量并将其第一个索引分配给一个变量并将其第二个索引分配给另一个变量来单独分配(解构只是使这更容易)。
示例:演示在功能组件中使用状态变量以及如何相应更新它的程序。
文件名-App.js
javascript
import React, { useState } from 'react';
function App() {
const [click, setClick] = useState(0);
// using array destructuring here
// to assign initial value 0
// to click and a reference to the function
// that updates click to setClick
return (
You clicked {click} times
);
}
export default App;
输出:
useState() 的工作一开始可能看起来很奇怪。毕竟,每次渲染时,被渲染的函数都是一个新函数——那么“状态”如何持续存在?在幕后,有一个对象代表内存中的功能组件,它有自己的堆栈。每当使用 useState() 挂钩时,状态变量的值都会更改,并且新变量将存储在堆栈中的新单元格中。堆栈指针同时递增以指向最后一个单元。此堆栈指针指向的值在每次渲染后使用。在用户故意刷新时,堆栈被转储,并且在渲染组件时完成内存中的新分配。
示例:在更新“状态”变量的值时演示如何使用最后一个值的程序。
文件名-App.js
javascript
import React, { useState } from 'react';
function App() {
const [click, setClick] = useState(0);
return (
You've clicked {click} times!
The number of times you have clicked
is {click%2==0?'even!':'odd!'}
);
}
export default App;
输出:
请注意,在上面的示例中,我们在 setClick() 中使用了一个箭头函数,该函数获取 click 的先前值并使用它用新值更新它。这种形式在需要根据状态变量的值执行数据操作的情况下很有用。在捕获和更改堆栈中的旧值之一而不是最新值的情况下,传递函数也很有用。
状态变量也可以是数组。当需要处理多个值而不需要使用 useState() 声明多个状态变量时,这尤其有用。
示例:演示将数组用作状态变量的程序(使用 useState())。
文件名-App.js
javascript
import React, { useState } from 'react';
function App() {
const [click, setClick] = useState([]);
const addNumber = () => {
setClick([
...click,
{
id: click.length,
value: Math.random() * 10
}
]);
};
return (
{click.map(item => (
- {item.value}
))}
);
}
export default App;
输出:
在使用数组时,useState() 与 setState()函数(用于更改基于类的组件中的状态变量的值)的工作方式不同。 setClick() 不会在被调用时将新值与现有值合并,它只是用新值覆盖它们。因此,有必要找到一种解决方法来附加现有值,这是在扩展运算符的帮助下在 addNumber() 内部函数中完成的。该函数创建一个具有特定 id 和值的新变量,并将其添加到现有数组(其值使用扩展运算符复制到函数中)。
如果需要一次处理多种类型的数据,最好的方法是使用对象。虽然可以使用单独的状态变量完成相同的工作,但从长远来看,对象可以使工作更加高效(也可以使用更少的 useState() 声明来解决问题)。
示例:演示将对象用作状态变量的程序(使用 useState())。
文件名-App.js
javascript
import React, { useState } from 'react';
function App() {
const [data, setData] = useState({
username: '',
password: ''
});
const [form, setForm] = useState({
username: '',
password: ''
});
const [submit, submitted] = useState(false);
const printValues = e => {
e.preventDefault();
setForm({
username: data.username,
password: data.password
});
submitted(true);
};
const updateField = e => {
setData({
...data,
[e.target.name]: e.target.value
});
};
return (
{submit?form.username:null}
{submit?form.password:null}
);
}
export default App;
输出:
在上面的示例中,“data”变量用于临时存储用户名和密码字段的输入值。再次使用扩展运算符来复制字段的现有值并相应地更新它。 'form' 变量用于存储通过组件中使用的表单提交的值的值 - 然后显示在表单下方。请注意,在更新“表单”状态变量时,扩展运算符不与 setForm() 一起使用,原因很简单,即无需为用户名和密码字段的先前提交的值而烦恼。