官方文档
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。
一、State Hook
useState
就是一个 Hook (等下我们会讲到这是什么意思)。通过在函数组件里调用它来给组件添加一些内部 state。React 会在重复渲染时保留这个 state。useState
会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。它类似 class 组件的 this.setState
,但是它不会把新的 state 和旧的 state 进行合并。
- 一般来说,一个函数组件,在函数退出后变量就会”消失”,但是 state 中的变量会被 React 保留。
- 当我们点击按钮,调用setCount函数时,React会重新渲染这个组件,并把更新的count值传给这个组件
- useState()接受一个参数为默认值,该方法返回一个数组,第一个值为定义data的值,第二个为更新data的方法,他们总是成对出现的,
import React, { useState } from 'react'
function Demo1(props) {
//count代表state的变量
//setCount是一个function,如果我们要修改count变量,需要通过setCount来修改
let [count, setCount] = useState(0)
let [count2, setCount2] = useState(1)
let [count3, setCount3] = useState(2)
return (<div>
{count}
<button onClick={() => { setCount(++count) }}>点我修改count</button>
<br />
{count2}
<button onClick={() => { setCount2(++count2) }}>点我修改count2</button>
<br />
{count3}
<button onClick={() => { setCount3(++count3) }}>点我修改count3</button>
</div>)
}
export default Demo1;
注意点:不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确
function Form() {
const [name1, setName1] = useState('111');
if(name1!==''){
const [name2, setName2] = useState('222');
}
const [name3, setName3] = useState('333');
// ...
}
二、Effect Hook
- useEffect就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API。
- 在调用这个hook时,就是告诉React在完成对DOM的更改后运行这个hook,在这里你可以访问到state和props。 ```javascript import React, { useState,useEffect } from ‘react’ import Child from ‘./Child.jsx’
function Demo2(props) { //count代表state的变量 //setCount是一个function,如果我们要修改count变量,需要通过setCount来修改 let [count, setCount] = useState(0) let [count2, setCount2] = useState(1)
//useEffect函数可以来模拟class组件的中指定生命周期的钩子函数 componentDidMount,componentDidUpdate,componentWillUnmount
//相当于componentDidMount 、componentDidUpdate
useEffect(()=>{
console.log("xxxxxxxxxxx",count)
})
//相当于componentDidMount
useEffect(()=>{
console.log("yyyyyyyyy")
},[])
//当count2的值被改变之后执行当前的useEffect,其他值改变不会执行这个useEffect
useEffect(()=>{
console.log("zzzzzzzzzzzzz")
},[count2])
//useEffect函数中return的function会在组件重新渲染的时候以及组件卸载的时候执行
useEffect(()=>{
return ()=>{
console.log('hello Hook')
}
})
return (<div>
{count}
<button onClick={() => { setCount(++count) }}>点我修改count</button>
<br />
<button onClick={() => { setCount2(++count2) }}>点我修改count2</button>
<br />
<Child></Child>
</div>)
}
export default Demo2;
<a name="pFqQO"></a>
## 三、Ref Hook
" ref " 对象是一个通用容器,其current属性是可变的
<a name="u6JaH"></a>
### 3-1 保存dom
```javascript
function Test() {
const t = useRef(null);
useEffect(() => {
console.log(t.current); // div
});
return (
<div ref={t}> ... </div>
);
}
3-2 保存时间秩序
function Test() {
const t = useRef(null);
function handleClick() {
t.current = setTimeout(() => console.log(1), 2000);
}
function handleClear() {
clearTimeout(t.current);
}
return (
<>
<button onClick={handleClick}>start</button>
<button onClick={handleClear}>clear</button>
</>
);
}
3-3 存储以前的值
function Test() {
const t = useRef(null);
const [name, setName] = useState("ajanuw");
useEffect(() => {
t.current = name;
});
const prevName = t.current;
return (
<div>
<input value={name} onChange={e => setName(e.target.value)} />
<h2>{name}</h2>
<p>{prevName}</p>
</div>
);
}
四、Context Hook
接收一个 context 对象(React.createContext
的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider>
的 value
prop 决定。
#1.App.jsx
import React from 'react'
import Demo3 from '@/components/Demo3'
import MyContext from './context.js'
function App(){
return (<MyContext.Provider value={{name:"zhangsan"}}>
App
<Demo3></Demo3>
</MyContext.Provider>)
}
export default App;
#2/context.js
import React from 'react'
const MyContext = React.createContext();
export default MyContext;
#3.Child.jsx
import React,{useContext} from 'react'
import MyContext from '@/context.js'
export default function(props){
//在子组件中获取父组件发布的数据
const contextValue = useContext(MyContext);
console.log(contextValue)
return (<div>xx</div>)
}