不废话,必须把函数组件的hooks啃下来!!
1.最简单的 useState
暴露初始值和改变的方法
const [A,changeA] = useState(0);
return (
<button onClick = {()=>changeA(A++)} > { A } < /button>
)
import React,{useState} from "react";
function Example() {
const [count, setCount] = useState(0);
const [person, setPerson] = useState({name:'jimmy',age:22});
return (
<div>
<p>name {person.name} </p>
// 如果新的 state 需要通过使用先前的 state 计算得出,那么可以将回调函数当做参数传递给 setState。
// 该回调函数将接收先前的 state,并返回一个更新后的值。
<button onClick={() => setCount(count=>count+1)}>Click me</button>
<button onClick={() => setPerson({name:'chimmy'})}>Click me</button>
</div>
);
}
export default Example;
2.useEffect
可以看做是函数组件的声明周期...
根据参数和return的内容 可以模拟不同的生命周期
useEffect 有第二个参数代表在初始化时执行一次
return 出的为组件解除绑定需要执行的方法
import React, { useState, useEffect } from "react";
function Example() {
const [count, setCount] = useState(0);
const [number, setNumber] = useState(1);
useEffect(() => {
console.log("我只会在cout变化时执行");
return ()=>{
console.log("我只会在组件解除绑定时执行");
}
}, [count]); //传入依赖值,根据依赖来决定是否执行
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click cout</button>
<button onClick={() => setNumber(number + 1)}>Click number</button>
</div>
);
}
export default Example;
3.useContext
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
// 创建两个context
export const UserContext = React.createContext();
export const TokenContext = React.createContext();
ReactDOM.render(
<UserContext.Provider value={{ id: 1, name: "chimmy", age: "20" }}>
<TokenContext.Provider value="我是token">
<App />
</TokenContext.Provider>
</UserContext.Provider>,
document.getElementById("root")
);
import React, { useContext } from "react";
import { UserContext, TokenContext } from "./index";
//通过useContext 可以获取顶层的状态
function Example() {
let user = useContext(UserContext);
let token = useContext(TokenContext);
console.log("UserContext", user);
console.log("TokenContext", token);
return (
<div>
name:{user?.name},age:{user?.age}
</div>
);
}
export default Example;
4.useReducer
个人解读
-
useReducer 接受初始值并在useState基础上添加处理函数
-
暴露出两个内容,触发处理函数的方法和初始值
-
useReducer的处理函数接受两个参数,state 和 action
-
state 为初始值 ,action 为触发处理函数时传递的参数
import React, { useReducer } from "react";
export default function Home() {
function reducer(state, action) {
switch (action.type) {
case "increment":
return { ...state, counter: state.counter + 1 };
case "decrement":
return { ...state, counter: state.counter - 1 };
default:
return state;
}
}
const [state, dispatch] = useReducer(reducer, { counter: 0 });
return (
<div>
<h2>Home当前计数: {state.counter}</h2>
<button onClick={(e) => dispatch({ type: "increment" })}>+1</button>
<button onClick={(e) => dispatch({ type: "decrement" })}>-1</button>
</div>
);
}
5.useCallback 和 useMemo
两个方法都依赖于绑定的值,在值改变后会执行相应的回调,区别是useCallback返回一个方法,useMemo返回处理的结果
import React, { useState ,useCallback, useMemo } from "react";
// 子组件
function Childs(props) {
console.log("子组件渲染了");
return (
<>
<button onClick={props.onClick}>改标题</button>
<h1>{props.name}</h1>
</>
);
}
const Child = React.memo(Childs);
function App() {
const [title, setTitle] = useState("这是一个 title");
const [subtitle, setSubtitle] = useState("我是一个副标题");
const [count, setCount] = useState(100000);
const [show, setShow] = useState(true);
const total = useMemo(() => {
return calcNumber(count);
}, [count]);
const callback = () => {
setTitle("标题改变了");
};
function calcNumber(count) {
let total = 0;
for (let i = 1; i <= count; i++) {
total += i;
}
return total;
}
return (
<div className="App">
<h1>{title}</h1>
<h2>{subtitle}</h2>
<h2>计算数字的和: {total}</h2>
<button onClick={() => setSubtitle("副标题改变了")}>改副标题</button>
<Child onClick={useCallback(callback, [])} name="桃桃" />
<button onClick={e => setCount(count + 1)}>+1</button>
<button onClick={e => setShow(!show)}>show切换</button>
</div>
);
}
6.useRef
//在class中通过 React.createRef() 来绑定和操作dom hooks中有不同的api
import React, { useRef } from "react";
function Example() {
const divRef = useRef();
function changeDOM() {
// 获取整个div
console.log("整个div", divRef.current);
// 获取div的class
console.log("div的class", divRef.current.className);
// 获取div自定义属性
console.log("div自定义属性", divRef.current.getAttribute("data-clj"));
}
return (
<div>
<div className="div-class" data-clj="我是div的自定义属性" ref={divRef}>
我是div
</div>
<button onClick={(e) => changeDOM()}>获取DOM</button>
</div>
);
}
export default Example;