HOOK这个单词的意思是钩子,用来将外部功能“钩”进来
四个最常用的钩子
- useState
- useContext
- useReducer
- useEffect
useState() 状态钩子
- useState()用于维函数引入状态state ,纯函数不能有状态,所以状态放在钩子里面 ```javascript //引入钩子组件 import React, { useState } from “react”;
export default function Button() { //用钩子引入state状态 //数组的第一个成员是一个变量,指向状态初始值,第二个值是一个函数,用来更新状态,约定是 //set前缀加上状态的变量名 const [buttonText, setButtonText] = useState(“Click me, please”); //改变state状态 function handleClick() { return setButtonText(“Thanks, been clicked!”); } return ; }
<a name="S4YY3"></a>
### useContext()共享状态钩子
```javascript
import React, { useContext } from "react";
import ReactDOM from "react-dom";
//创建一个Context
const AppContext = React.createContext({});
const Navbar = () => {
//子组件通过useContext() 钩子用来引入Context对象,从中获取username属性
const { username } = useContext(AppContext)
return (
<div className="navbar">
<p>AwesomeSite</p>
<p>{username}</p>
</div>
)
}
const Messages = () => {
const { username } = useContext(AppContext)
return (
<div className="messages">
<h1>Messages</h1>
<p>1 message for {username}</p>
<p className="message">useContext is awesome!</p>
</div>
)
}
//使用AppContext.Provider 提供一个Context对象,这个对象可以被组建共享
function App() {
return (
<AppContext.Provider value={{
username: 'superawesome'
}}>
<div className="App">
<Navbar />
<Messages />
</div>
</AppContext.Provider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
userReducer(): action 钩子
import React, { useReducer } from "react";
import ReactDOM from "react-dom";
//Reducer修改state返回新的state
const myReducer = (state, action) => {
switch(action.type) {
case('countUp'):
return {
...state,
count: state.count + 1
}
default:
return state
}
}
function App() {
//数组的第一个成员是当前状态,第二个成员是发送action的dispatch函数
const [state, dispatch] = useReducer(myReducer, { count: 0 })
return (
<div className="App">
<button onClick={() => dispatch({ type: 'countUp' })}>
+1
</button>
<p>Count: {state.count}</p>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
由于 Hooks 可以提供共享状态和 Reducer 函数,所以它在这些方面可以取代 Redux。但是,它没法提供中间件(middleware)和时间旅行(time travel),如果你需要这两个功能,还是要用 Redux。
useEffect():副作用钩子
- 用来引入有副作用的操作,最常见的就是向服务器请求数据,之前放在componentDidMount里面的代码,现在可以放在这里
- useEffect接收两个参数,第一个是函数,一步的操作代码放在里面,第二个是一个数组,用于给出Effect的依赖项,只要这个数组发生变化,useEffect()就会执行,第二个参数省略,每次组件渲染时,就会执行useRffect ```javascript import React, { useState, useEffect } from “react”; import ReactDOM from “react-dom”;
const Person = ({ personId }) => {
const [loading, setLoading] = useState(true);
const [person, setPerson] = useState({});
//用来执行有副作用的操作
useEffect(() => {
setLoading(true);
fetch(https://swapi.co/api/people/${personId}/
)
.then(response => response.json())
.then(data => {
setPerson(data);
setLoading(false);
});
},
//第二个参数为数组,依赖的参数发生变化就会执行useEffect
[personId]);
if (loading === true) { return
Loading …
; }return (
You’re viewing: {person.name}
Height: {person.height}
Mass: {person.mass}
function App() { const [show, setShow] = useState(“1”);
return (
const rootElement = document.getElementById(“root”);
ReactDOM.render(
<a name="Fep7i"></a>
### useMemo 防止子组件重复执行
父组件状态发生变化,子组件也会重新执行一次,那么要防止子组件方法在任何情况下调用,我们可以使用useMemo来对方法进行阻止
```javascript
import React ,{useMemo} from 'react'
//子组件接收一个count,那么只有在count发生变化才会触发这个函数,否则就跳过
function Dom({count}){
let cc = useMemo(()=>{
return count *2
},[count])
return <div>
<h1>Dom {count}------{cc}</h1>
</div>
}
export default Dom
useRef
useRef 可以用来保存DOM和变量,进行一个缓存。
const inp = useRef(null)//初始化一个inp变量
return (
<div>
<input type='text' ref={inp} />{/* 保存DOM节点到inp上 */}
<button
onClick={() => {
console.log(inp.current.value)
//打印出来输入的值
}}>
改变一下
</button>
</div>
)
使用useContext、useReducer封装一个类似于redux仓库
- 第一步 创建store.js
```javascript
import { createContext } from “react”;
//定义共享数据
export const Context =createContext(null);
//定义仓库初始值
export const defayltState={
count:0
}
//定义修改数据方法
export default (state,action)=>{
switch(action.type){
} }case('add'):
return {
...state,
count:state.count + 1
}
default:
return state
- 第二步 父组件挂载context
```javascript
/** @format */
import React, { useState,useReducer } from 'react'
import Son from './son'
//引入配置
import myReducer,{defayltState,Context} from './store'
export default function Father() {
const [state,dispatch] = useReducer(myReducer,defayltState)
//调用后数组第一个成员是当前状态,第二个是发送action的dispatch函数
return (
//通过context 挂载共享属性
<Context.Provider value={{...state,dispatch}}>
<h1>{state.count}</h1>
<button onClick={()=>dispatch({type:'add'})}>add 1</button>
<Son></Son>
</Context.Provider>
)
}
- 第三步 在子组件调用 ```javascript import React,{useContext,useEffect} from ‘react’ import {Context} from ‘./store’;//引入context
function Son(){ const con = useContext(Context)//拿到数据 useEffect(()=>{ setTimeout(()=>{ console.log(‘200’) },1000) },[])//数组为空只有初始化页面执行,不传递参数每次数据更改都会执行 return