摘要: React示例教程莹规。
- 原文:快速了解 React Hooks 原理
- 譯者:前端小智
到 React 16.8 目前為止请梢,如果編寫函數(shù)組件正歼,然后遇到需要添加狀態(tài)的情況辐马,咱們就必須將組件轉(zhuǎn)換為類組件。
編寫 class Thing extends React.Component
局义,將函數(shù)體復制到render()
方法中喜爷,修復縮進,最后添加需要的狀態(tài)旭咽。
今天贞奋,可以使用 Hook 獲得相同的功能,并為自己節(jié)省了工作時間穷绵。在本文中轿塔,主要介紹useState
hook。
useState 做啥子的
useState
hook 允許咱們向函數(shù)組件添加狀態(tài)仲墨,我們通常稱這些為“ hooks”勾缭,但它們實際上是函數(shù),與 React 16.8 捆綁在一起目养。 通過在函數(shù)組件中調(diào)用useState
俩由,就會創(chuàng)建一個單獨的狀態(tài)。
在類組件中癌蚁,state
總是一個對象幻梯,可以在該對象上添加保存屬性。
對于 hooks努释,state 不必是對象碘梢,它可以是你想要的任何類型-數(shù)組、數(shù)字伐蒂、布爾值煞躬、字符串等等。每次調(diào)用useState
都會創(chuàng)建一個state
塊逸邦,其中包含一個值恩沛。
示例1:使用 useState 顯示/隱藏組件
這個示例是一個組件,它顯示一些文本缕减,并在末尾顯示一個read more
鏈接雷客,當單擊鏈接時,它展開剩下的文本桥狡。
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
// 兩個 props:
// text - 顯示的內(nèi)容
// maxLength - 在點擊“read more”之前顯示多少個字符
function LessText({ text, maxLength }) {
// 創(chuàng)建一個狀態(tài)佛纫,并將其初始化為“true”
const [hidden, setHidden] = useState(true);
if (text <= maxLength) {
return <span>{text}</span>;
}
return (
<span>
{hidden ? `${text.substr(0, maxLength).trim()} ...` : text}
{hidden ? (
<a onClick={() => setHidden(false)}> read more</a>
) : (
<a onClick={() => setHidden(true)}> read less</a>
)}
</span>
);
}
ReactDOM.render(
<LessText
text={`專注妓局、努力是成功的真正關(guān)鍵总放。把你的眼睛盯在目標上呈宇,然后朝著目標邁出下一步`}
maxLength={35}
/>,
document.querySelector('#root')
);
僅用一行代碼,我們就使這個函數(shù)組件有狀態(tài):
const [hidden, setHidden] = useState(true);
但是這個函數(shù)到底在做什么呢?如果每次渲染都調(diào)用它(確實如此)局雄,它又是如何保留狀態(tài)的甥啄。
Hooks 實現(xiàn)的技巧
這里的“神奇”之處是,React在每個組件的幕后維護一個對象炬搭,并且在這個持久對象中蜈漓,有一個“狀態(tài)單元”數(shù)組。當你調(diào)用useState
時宫盔,React
將該狀態(tài)存儲在下一個可用的單元格中融虽,并遞增數(shù)組索引。
假設你的 hooks
總是以相同的順序調(diào)用(如果遵循 hooks 的規(guī)則灼芭,它們將是相同的順序)有额,React能夠查找特定useState
調(diào)用的前一個值。對useState
的第一個調(diào)用存儲在第一個數(shù)組元素中彼绷,第二個調(diào)用存儲在第二個元素中巍佑,依此類推。
這也不是很神奇的事情寄悯,主要它依賴于你可能沒有想過的事實:咱們寫的的組件是由React
調(diào)用 萤衰,所以它可以在調(diào)用組件之前事先做好一些工作。 而且猜旬,渲染組件的行為不僅僅是函數(shù)調(diào)用脆栋。 像<Thing />
這樣的JSX
被編譯為React.createElement(Thing)
- 顯然 React 可以控制它的調(diào)用方式和時間。
示例2:根據(jù)之前的狀態(tài)更新狀態(tài)
看看另一個例子:根據(jù)前一個值更新state
的值洒擦。
咱們要造個計步器椿争,每點擊一次按鈕,就計一次秘遏,點擊完后丘薛,它會告訴你你走了多少步。
import React, { useState } from 'react';
function StepTracker() {
const [steps, setSteps] = useState(0);
function increment() {
setSteps(steps => steps + 1);
}
return (
<div>
總共走了 {steps} 步!
<br />
<button onClick={increment}>
點點我邦危,步數(shù)不是個事洋侨!
</button>
</div>
);
}
ReactDOM.render(
<StepTracker />,
document.querySelector('#root')
);
首先,通過調(diào)用useState
創(chuàng)建一個新的state
倦蚪,并將其初始化為0
希坚。它返回steps
的當前值0
和setSteps
函數(shù)來更新 steps
,用 increment
函數(shù)來對steps
進行增 1 操作陵且。
這里還可以優(yōu)化的提取increment
函數(shù)裁僧,可以直接將 increment
函數(shù)里面的內(nèi)聯(lián)到 onClick
里面:
<button onClick={() => setSteps(steps => steps + 1)}>
I took another step
</button>
示例3: state 作為數(shù)組
記住个束,state
可以保存任何你想要的值。下面是一個隨機數(shù)列表的例子聊疲,單擊按鈕將向列表添加一個新的隨機數(shù):
function RandomList() {
const [items, setItems] = useState([]);
const addItem = () => {
setItems([
...items,
{
id: items.length,
value: Math.random() * 100
}
]);
};
return (
<>
<button onClick={addItem}>Add a number</button>
<ul>
{items.map(item => (
<li key={item.id}>{item.value}</li>
))}
</ul>
</>
);
}
注意茬底,我們state
初始化為空數(shù)組[]
,并在addItem
函數(shù)中更新值获洲。
setItems
更新 state
不會將舊值“合并” - 它會使用新值覆蓋state
阱表。 這與this.setState
在類中的工作方式不同。
示例4:具有多個鍵的 state
再來看看贡珊,state
為對象的例子最爬,創(chuàng)建一個包含2個字段的登錄表單:username
和password
。
下面示例主要展示如何在一個state
對象中存儲多個值门岔,以及如何更新單個值爱致。
function LoginForm() {
const [form, setValues] = useState({
username: '',
password: ''
});
const printValues = e => {
e.preventDefault();
console.log(form.username, form.password);
};
const updateField = e => {
setValues({
...form,
[e.target.name]: e.target.value
});
};
return (
<form onSubmit={printValues}>
<label>
Username:
<input
value={form.username}
name="username"
onChange={updateField}
/>
</label>
<br />
<label>
Password:
<input
value={form.password}
name="password"
type="password"
onChange={updateField}
/>
</label>
<br />
<button>Submit</button>
</form>
);
}
如果想試試,可查看 CodeSandbox寒随。
首先糠悯,我們創(chuàng)建一個state
片段,并用一個對象初始化它
const [form, setValues] = useState({
username: '',
password: ''
})
這看起來像是在類中初始化狀態(tài)的方式牢裳。
還有一個處理提交的函數(shù)逢防,其中,e.preventDefault
來阻止頁面刷新并打印出表單值蒲讯。
updateField
函數(shù)更有意思忘朝。它使用setValues
傳遞一個對象,為了確迸邪铮現(xiàn)有的狀態(tài)不被覆蓋局嘁,這里使用了展開運算(...form
)。
代碼部署后可能存在的BUG沒法實時知道晦墙,事后為了解決這些BUG悦昵,花了大量的時間進行l(wèi)og 調(diào)試,這邊順便給大家推薦一個好用的BUG監(jiān)控工具 Fundebug晌畅。
原文:https://daveceddia.com/usestate-hook-examples/
關(guān)于Fundebug
Fundebug專注于JavaScript但指、微信小程序、微信小游戲抗楔、支付寶小程序棋凳、React Native、Node.js和Java線上應用實時BUG監(jiān)控连躏。 自從2016年雙十一正式上線剩岳,F(xiàn)undebug累計處理了20億+錯誤事件,付費客戶有陽光保險入热、核桃編程拍棕、荔枝FM晓铆、掌門1對1、微脈绰播、青團社等眾多品牌企業(yè)骄噪。歡迎大家免費試用!