1:第一个useState
用来声明和修改数据
import {useState} from "react"
let [num,setNum] = useState(0);
使用: {num}
修改:{setNum}
注意细节
1:useState是异步的;
2:useState(()=>state);
useState的数据 修改以后马上获取 可以使用回调
2:第二个useEffect 副作用函数
主要用来模拟生命周期 和数据监听
生命周期: 三个阶段 挂载 更新 销毁
useEffect有两个参数 第一个函数 第二个依赖项
如果依赖项不填 数据更新的时候都会触发
useEffect(() => {
console.log("页面加载");
console.log("实时的num为"+num);
},[num]);
useEffect(() => {
return () => {
console.log("页面销毁");
};
},[]);
let add = () => {
setnum(num + 1);
};
3:第三个hook useRef
import React, {useRef } from "react";
//声明
let usernameInput = useRef();
let userageInput = useRef();
//使用
<div>
<div>
姓名 <input ref={usernameInput} />
</div>
<div>
年龄 <input ref={userageInput} />
</div>
</div>
//取值
usernameInput.current.value;
//赋值
usernameInput.current.value = item.username;
userageInput.current.value = item.userage;
4:useContext 公共的上下文关系对象(跨层级的组件通信)
import React,{useContext} from 'react'
import NumContext from '../context/NumContext'
export default function Child2() {
let context = useContext(NumContext)
return (
<div>Child2
公共的数据为{context.num}
</div>
)
}
5: useReducer 分离和规范useSetate的写法
//之前 都是在一个方法里面
// const [list, setlist] = useState([]);
// //新增数据
// // setlist([...list,item])
// // setlist(list.filter(item=>item.id!==id));
// // setlist(list.map(item=>{
// // if(item.id ===id){ item.name="abc"}
// // return item
// // }))
分离以后
function reducer(state, action) {
//state表示数据(状态) action 描述的对象
switch (action.type) {
case "init":
return action.payload;
case "add":
return [...state, action.payload];
case "del":
return state.filter(item=>item.id!==action.payload)
default:
return state;
}
}
//使用
export default function UseReducer() {
const [state, dispatch] = useReducer(reducer, []);
useEffect(() => { //页面加载成功
dispatch({
type:"init",
payload:[{id:1},{id:2},{id:3}]
})
}, [])
let add = function () {
//调用接口 成功以后同步页面效果
dispatch({
type: "add",
payload: { id: 3 },
});
};
let delById = (payload) => {
dispatch({
type: "del",
payload,
});
};
return (
<div>
<button onClick={add}>新增</button>
<div className="tr">
<div className="td">编号</div>
<div className="td">操作</div>
</div>
{state.map((item) => {
return (
<div className="tr" key={item.id}>
<div className="td">{item.id}</div>
<div
className="td"
onClick={() => {
delById(item.id);
}}
>
删除
</div>
</div>
);
})}
</div>
);
}
6: useCallBack
父组件
import React,{useState} from 'react'
import Child3 from '../components/Child3'
export default function UseCallBack() {
const [num, setnum] = useState(10);
return (
<div>UseCallBack
<div>显示数据{num}<button onClick={()=>{
setnum(num+1);
}}>修改数据</button> </div>
<hr/>
<Child3></Child3>
</div>
)
}
子组件
import React from 'react'
export default function Child3() {
console.log("加载child3");
return (
<div>Child3</div>
)
}
问题:父组件中的数据变化了 子组件都会重新渲染 在类组件中shouldComponentUpdate 可以解决 return false
hooks中解决 :缓存组件(keep-alive)
import React,{memo} from 'react'
function Child3() {
console.log("加载child3");
return (
<div>Child3</div>
)
}
export default memo(Child3);
import React, { useCallback, useState } from "react";
import Child3 from "../components/Child3";
export default function UseCallBack() {
const [num, setnum] = useState(10);
const [n, setn] = useState(1)
let fn = useCallback(()=>{
console.log(n+"发生了改变");
},[n]);
return (
<div>
UseCallBack
<div>
显示数据{num}
<button
onClick={() => {
setnum(num + 1);
}}
>
修改数据
</button>{" "}
</div>
<div>
数据n为{n}
<button onClick={()=>{
setn(n+1);
}}>修改n</button>
</div>
<hr />
<Child3 fn={fn}></Child3>
</div>
);
}
7:useMemo 计算属性 根据指定的值的变化 生成新的值
import React, { useMemo, useState } from "react";
export default function UseMemo() {
const [num, setnum] = useState(10);
const [price, setprice] = useState(88);
const [n, setn] = useState(1);
let fn1 = function(){
console.log("开始计算");
return num * price;
}
let total= useMemo(() =>{
console.log("我也开始计算")
return num*price
} , [num,price])
return (
<div>
<div>
n为{n}
<button onClick={()=>{
setn(n+1);
}}>修改n</button>
</div>
UseMemo
<div>
数量{" "}
<input
value={num}
onChange={(e) => {
setnum(e.target.value);
}}
/>{" "}
</div>
<div>
价格{" "}
<input
value={price}
onChange={(e) => {
setprice(e.target.value);
}}
/>{" "}
</div>
总价{price*num}
<div>函数取总价 {fn1()}</div>
<div>统计{total}</div>
</div>
);
}
8:useRef
1:标记标签名称 想到了ref 方便组件内部使用
2:如果父组件想获取子组件的实例 比如子组件自身提供暴露的方法 forwarRef
import React,{useRef} from 'react'
export default function Child4({setMsg}) {
const msgInput = useRef();
return (
<div>Child4
<div>内容:<input ref={msgInput}/>
<button onClick={()=>{
setMsg(msgInput.current.value);
}}>给父组件</button>
</div>
</div>
)
}
3:useImperativeHandle 暴露子组件的方法给父组件 配合forwardRef来使用
import React,{useRef,forwardRef,useImperativeHandle} from 'react'
function Child4({setMsg},ref) {
const msgInput = useRef();
useImperativeHandle(ref, () => ({
getMsg: () => { //暴露子组件的方法给 父组件
return msgInput.current.value;
},
setMsg:(msg)=>{
msgInput.current.value = msg;
}
}));
return (
<div>Child4
<div>内容:<input ref={msgInput}/>
<button onClick={()=>{
setMsg(msgInput.current.value);
}}>给父组件</button>
</div>
</div>
)
}
export default forwardRef(Child4);
使用;
return (
<div>
<button onClick={()=>{
child4.current.setMsg("来自爸爸的爱");
}}>设置子组件的内容</button>
UseRef
显示子组件的值{msg}
<button onClick={()=>{
setMsg(child4.current.getMsg());
}}>我要获取子组件的内容</button>
<Child4 setMsg={setMsg} ref={child4}></Child4>
</div>
)
9:useEffect 的函数会在组件渲染到屏幕之后执行 :useLayoutEffect则是在DOM结构更新后、渲染前执行,相当于有一个防抖效果
import { useLayoutEffect,useEffect, useState } from "react";
export default function App() {
const [value, setValue] = useState(0);
useLayoutEffect(() => {
if (value === 0) {
setValue(10 + Math.random() * 200);
}
}, [value]);
// console.log("render", value);
return (
<div onClick={() => setValue(0)}>value: {value}</div>
);
}
//hooks ahooks
//redux mobx RTK
//antd -pro antd - mobile
//React-native taro
10:ahooks 文档
https://ahooks.gitee.io/zh-CN/hooks/use-request/index
数据请求的例子
import React, { useEffect, useState } from "react";
import { useRequest } from "ahooks";
import { userQuery, userDelById, userAdd } from "../service/userService";
export default function UseRequest() {
const [username, setUsername] = useState("");
const [userage, setUserage] = useState("");
//页面加载的方法
let { data, run: GetList } = useRequest(userQuery, {
manual: true, //手动触发
debounceWait: 500, //表示两秒内只触发一次
});
useEffect(() => {
GetList({}); //页面加载 触发
}, []);
//删除的方法
let { run: delListById } = useRequest(userDelById, {
manual: true, //表示手动触发
onSuccess: () => {
GetList({}); //获取最新的数据
},
});
//新增的方法
let { run: addList } = useRequest(userAdd, {
manual: true, //表示手动触发
onSuccess: () => {
GetList({}); //获取最新的数据
},
});
return (
<div>
<div>
姓名{" "}
<input
value={username}
onChange={(e) => {
setUsername(e.target.value);
}}
/>{" "}
</div>
<div>
年龄{" "}
<input
value={userage}
onChange={(e) => {
setUserage(e.target.value);
}}
/>{" "}
</div>
<button
onClick={() => {
addList({ username, userage });
}}
>
新增
</button>
<hr />
<input
placeholder="用户名查询"
onChange={(e) => {
GetList({ username_like: e.target.value }); //表示根据用户名进行查询
}}
/>
<div className="tr">
<div className="td">编号</div>
<div className="td">姓名</div>
<div className="td">年龄</div>
<div className="td">操作</div>
</div>
{data?.data.map((item) => {
return (
<div className="tr" key={item.id}>
<div className="td">{item.id}</div>
<div className="td">{item.username}</div>
<div className="td">{item.userage}</div>
<div
className="td"
onClick={() => {
delListById(item.id);
}}
>
删除
</div>
</div>
);
})}
</div>
);
}
页面同步更新效果
import React, { useEffect, useState } from "react";
import { useRequest, useSetState } from "ahooks";
import { userQuery, userDelById, userAdd } from "../service/userService";
export default function UseRequest() {
const [username, setUsername] = useState("");
const [userage, setUserage] = useState("");
const [list, setList] = useState([]);
const [info, setinfo] = useSetState({
username: "leson",
userage: 18,
});
//页面加载的方法
let { run: GetList } = useRequest(userQuery, {
manual: true, //手动触发
debounceWait: 500, //表示两秒内只触发一次
onSuccess: (res) => {
setList(res.data);
},
});
useEffect(() => {
GetList({}); //页面加载 触发
}, []);
//删除的方法
let { run: delListById } = useRequest(userDelById, {
manual: true, //表示手动触发
throttleWait: 3000, //节流
onSuccess: (res, params) => {
// console.log(params);
// GetList({}); //获取最新的数据
setList(list.filter((item) => item.id !== params[0]));
},
});
//新增的方法
let { run: addList } = useRequest(userAdd, {
manual: true, //表示手动触发
throttleWait: 1000, //节流
onSuccess: (res, params) => {
// console.log(res.data);
// console.log(params);
// GetList({}); //获取最新的数据
setList([...list, res.data]);
},
});
return (
<div>
<div>
姓名{" "}
<input
value={username}
onChange={(e) => {
setUsername(e.target.value);
}}
/>{" "}
</div>
<div>
年龄{" "}
<input
value={userage}
onChange={(e) => {
setUserage(e.target.value);
}}
/>{" "}
</div>
<button
onClick={() => {
addList({ username, userage });
}}
>
新增
</button>
<hr />
<input
placeholder="用户名查询"
onChange={(e) => {
GetList({ username_like: e.target.value }); //表示根据用户名进行查询
}}
/>
<div className="tr">
<div className="td">编号</div>
<div className="td">姓名</div>
<div className="td">年龄</div>
<div className="td">操作</div>
</div>
{list.map((item) => {
return (
<div className="tr" key={item.id}>
<div className="td">{item.id}</div>
<div className="td">{item.username}</div>
<div className="td">{item.userage}</div>
<div
className="td"
onClick={() => {
delListById(item.id);
}}
>
删除
</div>
</div>
);
})}
<div>
对象的更新 姓名{info.username} 年龄{info.userage}
<button
onClick={() => {
setinfo({ userage: 100 });
}}
>
更新
</button>
</div>
</div>
);
}