首先,Hook是什么?
Hook
Hook 是 React 团队在 React 16.8 版本中提出的新特性,在遵循函数式组件的前提下,为已知的 React 概念提供了更直接的 API:props,state,context,refs 以及声明周期,目的在于解决常年以来在 class 组件中存在的各种问题,实现更高效的编写 react 组件。
Hook的使用规则是什么?
Hook 就是 Javascript 函数,使用它们时有两个额外的规则:
函数外层调用 Hook,不要在循环、条件判断或者子函数中调用。
只能在 React 的函数组件和 自定义 Hook
Hook的使用!
useState :
useState只能在 React 的函数组件和自定义 Hook
const [state, setState] = useState(initialState);
Hook 是什么?
useState :方法的使用
代码如下:
import React, { useState } from 'react';
export default function UseState() {
const [count, setCount] = useState(0);
return (
<div>
{/* 点击按钮 count-1或+1 */}
<button onClick={() => setCount(count - 1)}>-</button>
<button onClick={() => setCount(count + 1)}>+</button>
{/* input发生变化 获取count */}
<input type="text" value={count} onChange={(e) => setCount(e.target.value)} />
</div>
);
}
useEffect:
useEffect 做了什么?
为什么在组件内部调用 useEffect?
useEffect 会在每次渲染后都执行吗? 是的,默认情况下,它在第一次渲染之后和每次更新之后都会执行。(我们稍后会谈到如何控制它。)你可能会更容易接受 effect 发生在“渲染之后”这种概念,不用再去考虑“挂载”还是“更新”。React 保证了每次运行 effect 的同时,DOM 都已经更新完毕。
useEffect () 本身是一个函数,由 React 框架提供,在函数组件内部调用即可。
useEffect(didUpdate);
useEffect 的使用
import React, { useState, useEffect } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
// useEffect 内的回调函数会在初次渲染后和更新完成后执行
// 相当于 componentDidMount 和 componentDidUpdate
useEffect(() => {
document.title = `您 单击了 ${count} 次`;
});
//这里也可以写成
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // 仅在 count 更改时更新
return (
<div>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}
useContext :
useContext可以帮助我们跨越组件层级直接传递变量,实现数据共享。
const value = useContext(MyContext);
useContext 的使用
父组件写入
import React,{useEffect,useState,useRef,createRef} from 'react'
import {ThemeContext,ThemeContext2} from './context'
import A3 from './components/A3'
function A2(props) {
return (
<div><A3 /></div>
)
}
//父子传值
function A1(props) {
const [x1,setX1]=useState('小蓝')
return (
<ThemeContext2.Provider value={{title1:x1}}>
<A2 />
</ThemeContext2.Provider>
)
}
export default function Context(props){
const [name,setName]=useState("小白");
const fn=opt=>{
// console.log(opt,'opt')
}
return (
<ThemeContext.Provider value={{title:'小花'}}>
<A1
x2={fn}
/>
</ThemeContext.Provider>
)
}
context页面
import React from "react";
// createContext 创建 Context 对象
export const ThemeContext =React.createContext();
export const ThemeContext2 =React.createContext();
子组件 A3页面:
import React,{useContext} from 'react'
import {ThemeContext,ThemeContext2} from '../context'
export default function A3 (props){
const values=useContext(ThemeContext);
const values2=useContext(ThemeContext2);
return (
<>
<h2>A1: {values.title}</h2>
<h2>A3:{values2.title1}</h2>
</>
)
}
子组件 Acontext页面
import React,{useContext} from 'react'
import {ThemeContext} from '../context'
export default function Acontext (props){
const values=useContext(ThemeContext);
const {xxx}=props
return (
<>
<h1>A3:{xxx}</h1>
<h2>A3:{values.title}</h2>
</>
)
}
useMemo :
useMemo接收两个参数,分别是函数和一个数组(实际上是依赖),函数里return 函数,数组内存放依赖
useMemo的使用:
import React, { useState, useMemo } from 'react';
function counterText({ countInfo }) {
return (
<p>{countInfo.name}: {countInfo.number}</p>
);
}
// // 使用 React.memo 检查 props 变更,复用最近一次渲染结果
const CounterText = React.memo(counterText);
export default function Counter() {
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(0);
const countInfo1 = {
name: 'count1',
number: count1
};
// 使用 useMemo 缓存最近一次计算结果,会在依赖项改变时才重新计算
const countInfo2 = useMemo(() => ({
name: 'count2',
number: count2
}), [count2]);
return (
<>
<div>
<CounterText countInfo={countInfo1} />
<button onClick={() => setCount1(count1 + 1)}>Add count1</button>
</div>
<div>
<CounterText countInfo={countInfo2} />
<button onClick={() => setCount2(count2 + 1)}>Add count2</button>
</div>
</>
);
}
useCallBack :
是为了缓存方法。我们可以通过自定义hooks函数来使用一下useCallback,我们可以通过自定义hooks函数来实现一个获取窗口大小的函数。
useCallback的使用:
import React, { ReactElement, useCallback, useState } from "react";
const Example = () => {
const [n, setN] = useState<number>(0);
const [m, setM] = useState<number>(10);
console.log("执行最外层盒子了");
const addN = useCallback(() => {
setN(n + 1);
}, [n]);
const addM = useCallback(() => {
setM(m + 1);
}, [m]);
return (
<div style={{ textAlign: "center", marginTop: 50 }}>
最外层盒子
<Child1 value={n} onClick={addN} />
<Child2 value={m} onClick={addM} />
<button onClick={addN}>n+1</button>
<button onClick={addM}>m+1</button>
</div>
);
};
interface childProp {
value: number;
onClick?: () => void;
}
const Child1 = React.memo((props: childProp): ReactElement<childProp> => {
console.log("执行子组件1了");
return <div>子组件1上的n:{props.value}</div>;
});
const Child2 = React.memo((props: childProp): ReactElement<childProp> => {
console.log("执行子组件2了");
return <div>子组件2上的m:{props.value}</div>;
});
export default Example;
useRef:
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。
useRef 的使用:
import React, { useRef } from "react";
export default function App() {
const r = useRef(0);
console.log(r);
const add = () => {
r.current += 1;
console.log(`r.current:${r.current}`);
};
return (
<div className="App">
<h1>r的current:{r.current}</h1>
<button onClick={add}>点击+1</button>
</div>
);
}
useReducer:
使用useReducer接收Reducer函数和一个初始state,并返回当前值state与dispatch函数,并且当触发事件时,使用dispatch传递action,让reducer计算出新的state
可以让你通过 reducer 来管理组件本地的复杂 state。
Reducers 非常便于单独测试,且易于扩展,以表达复杂的更新逻辑。如有必要,您可以将它们分成更小的 reducer。
export default function App() {
const initialState = { n: 1 };
const [state, dispatch] = useReducer(reducer, initialState);
//使用useReducer接收reducer参数和初始state
return (
<>
<div>{state.n}</div>
<button
onClick={() => {
dispatch({ type: "add" }); // 传递action
}}
>
点击+
</button>
<button
onClick={() => {
dispatch({ type: "sub" });//传递action触发reducer函数
}}
>
点击-
</button>
</>
);
}