一、hooks是什么,在什么时候使用?
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。Hook 是一个特殊的函数,它可以让你“钩入” React 的特性。例如,useState 是允许你在 React 函数组件中添加 state 的 Hook。稍后我们将学习其他 Hook。
如果你在编写函数组件并意识到需要向其添加一些 state,以前的做法是必须将其它转化为 class。现在你可以在现有的函数组件中使用 Hook。
二、为什么使用hooks
官方回答:
React 没有提供将可复用性行为“附加”到组件的途径(例如,把组件连接到 store)。如果你使用过 React 一段时间,你也许会熟悉一些解决此类问题的方案,比如 render props 和 高阶组件。但是这类方案需要重新组织你的组件结构,这可能会很麻烦,使你的代码难以理解。如果你在 React DevTools 中观察过 React 应用,你会发现由 providers,consumers,高阶组件,render props 等其他抽象层组成的组件会形成“嵌套地狱”。尽管我们可以在 DevTools 过滤掉它们,但这说明了一个更深层次的问题:React 需要为共享状态逻辑提供更好的原生途径。
你可以使用 Hook 从组件中提取状态逻辑,使得这些逻辑可以单独测试并复用。Hook 使你在无需修改组件结构的情况下复用状态逻辑。 这使得在组件间或社区内共享 Hook 变得更便捷。
复杂组件变得难以理解 为了解决这个问题,Hook 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据),而并非强制按照生命周期划分。你还可以使用 reducer 来管理组件的内部状态,使其更加可预测。我们将在使用 Effect Hook 中对此展开更多讨论
难以理解的 class 为了解决这个问题,Hook 使你在非 class 的情况下可以使用更多的 React 特性。 从概念上讲,React 组件一直更像是函数。而 Hook 则拥抱了函数,同时也没有牺牲 React 的精神原则。Hook 提供了问题的解决方案,无需学习复杂的函数式或响应式编程技术。
三、使用方法
常用的hooks有以下几种
useState,useEffect,useRef,useContext
useSelector,useDispatch
自定义hooks
1. useState(state,setState)
函数组件不需要构造函数,可以通过调用 useState 来初始化 state
import React, { useState } from "react"; export default function Button() { const [buttonText,setButtonText] = useState("点击前"); const handleClick = () => { setButtonText("点击后"); } return <button onClick={handleClick}>{buttonText}</button>; }
2. useEffect
useEffect 拥有两个参数,第一个参数作为回调函数会在浏览器布局和绘制完成后调用,因此它不会阻碍浏览器的渲染进程。第二个参数是一个数组
import React, { useState, useEffect } from 'react'; const Count = (props) => { const [count, setCount] = useState(0); useEffect(() => { let timer = setInterval(() => { setCount(count + 1) }, 1000); // 当在 useEffect 的回调函数中返回一个函数时,这个函数会在组件卸载前被调用 return () => clearInterval(timer) // count发生变化时再次执行 }, [count]); return <div> {count} </div> } export default Count;
3.useRef
useRef
返回一个可变的 ref 对象,其 .current
属性被初始化为传入的参数(initialValue
)。返回的 ref 对象在组件的整个生命周期内保持不变
import React, { useRef, useEffect } from "react"; export default function Test() { // 初始化一个useRef const box = useRef(null); useEffect(() => { // 通过.current获取 console.log(box.current) }, []) return ( <div ref={box}>this is a box</div> ); }
4.useContext
接收一个 context 对象,并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 的
value
prop 决定
//父组件 import React from "react"; export const TextContext = React.createContext({}); <TextContext.Provider value={{ text: "this is a text" }}> <Child></Child> </TextContext.Provider> //子组件接收 import React, { useContext } from "react"; import { TextContext } from './parent'; export default function MemberPop() { const { text } = useContext(TextContext); }
5. 自定义hooks
自定义 Hook 是一个函数,其名称以 “use
” 开头,函数内部可以调用其他的 Hook。
/** * 自定义一个hooks * 返回鼠标所在位置 */ import React, { useState, useEffect } from 'react' const useMousePosition = () => { const [position, setPosition] = useState({ x: 0, y: 0 }) useEffect(() => { const updateMouse = (e) => { setPosition({ x: e.clientX, y: e.clientY }) } document.addEventListener('mousemove', updateMouse) }, []) return position } export default useMousePosition //使用时引入自定义hooks import React from 'react' import useMousePosition from './hooks' export default function App() { const position = useMousePosition() return ( <div> <div>x: {position.x}</div> <div>y: {position.y}</div> </div> ) }