useState
useState 向组件中添加状态变量
状态是只读的,不可以直接修改
对于对象类型的状态变量,应该传递一个新的对象来更改
需要对象展开,并重新赋值,进行增加或者修改。
如果需要删除,则使用 filter。
import { useState } from "react";function App() {const [arr, setArr] = useState([{ id: 1, name: 'zhangsan' },{ id: 2, name: 'lisi' },{ id: 3, name: 'wangwu' }]);const content = arr.map((item, index) => {return <li key={item.id}>{item.name}</li>})const deleteVar = () => {setArr(arr.filter(item => item.name !== 'zhangsan'))}return (<><ul>{content}</ul><button onClick={deleteVar}>点击删除zhangsan</button></>)
}export default App
useReducer
让 React 管理多个相对关联的状态数据
import { useReducer } from "react"
// 1. 定义reducer函数,根据不同的action返回不同的状态
function reducer(state, action) {switch (action.type) {case 'ADD':return state + action.payloadcase 'SUB':return state - 1default:return state}
}function App() {// 2. 组件中调用 useReducer, 0 是初始化参数const [state, dispatch] = useReducer(reducer, 0)return (<div className="App">{state}{/* 3. 调用dispatch 产生一个新的状态,匹配事件(可传参) 更新 UI */}<button onClick={() => { dispatch({ type: 'ADD', payload:100 }) }}>+</button><button onClick={() => { dispatch({ type: 'SUB' }) }}>-</button></div>)
}export default App;
useRef
- 进行数据存储 值可以手动修改 不是响应式数据
- 获取 dom 节点
数据存储
import {useRef, useState} from "react";function App() {const [count, setCount] = useState(0)// useState 进行数据存储 值可以手动修改 不是响应式数据const preCount = useRef()function handleClick() {preCount.current = countsetCount(count + 1)}return (<><p>最新的 count:{count}</p><p>上次的 count:{preCount.current}</p><button onClick={handleClick}>增加count</button></>)
}export default App;
获取 dom 节点
import {useRef, useState} from "react";function App() {const inputRef = useRef(null);function handleClick() {inputRef.current.focus();}return (<><input ref={inputRef} /><button onClick={handleClick}>聚焦输入框</button></>);
}export default App;
获取组件
import {forwardRef, useImperativeHandle, useRef} from "react";// 默认子组件不对外开放自身的功能 需要 forwardRef 进行包裹
const Child = forwardRef(function (props, ref) {// 暴露给父组件的方法useImperativeHandle(ref, () => ({myFn: () => {console.log('子组件myFn方法')}}))return (<div>Child 子组件</div>)
})function App() {const childRef = useRef();function handleClick() {childRef.current.myFn();}return (<><Child ref={childRef}/><button onClick={handleClick}>按钮</button></>);
}export default App;
useContext
多层级通信 - useContext
官方文档:useContext
import {createContext, useContext, useState} from "react";function Section({children}) {const level = useContext(LevelContent)return (<section className="section">{/*逐渐从上层提供的LevelContext中取值*/}<LevelContent.Provider value={level + 1}>{/*children 也就是 heading 需要使用 useContext*/}{children}</LevelContent.Provider></section>);
}function Heading({children}) {const level = useContext(LevelContent)switch (level) {case 1:return <h1>{children}</h1>;case 2:return <h2>{children}</h2>;case 3:return <h3>{children}</h3>;case 4:return <h4>{children}</h4>;case 5:return <h5>{children}</h5>;case 6:return <h6>{children}</h6>;default:throw Error('未知的 level:' + level);}
}const LevelContent = createContext(0)function App() {return (<Section><Heading>主标题</Heading><Section><Heading>副标题</Heading><Heading>副标题</Heading><Heading>副标题</Heading><Section><Heading>子标题</Heading><Heading>子标题</Heading><Heading>子标题</Heading><Section><Heading>子子标题</Heading><Heading>子子标题</Heading><Heading>子子标题</Heading></Section></Section></Section></Section>)
}export default App;
useEffect
useEffect 在组件中创建由渲染本身引起的操作(如发送 Ajax 请求,更改 DOM 等),即非用户操作。
副作用函数随着依赖项的触发而执行。
清理副作用一般在组件卸载时执行
useEffect(() =>{// 实现副作用逻辑return ()=> {// 清除副作用逻辑}
}, [] )
import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from "react";function App() {const [count, setCount] = useState(0)const handleIncrement = ()=>setCount(count + 1)const handleDecrement = ()=>setCount(count - 1)useEffect(() => {console.log('useEffect')}, [count]);return (<><div style={{ padding: 10}}><button onClick={handleIncrement}>+</button><span> {count} </span><button onClick={handleDecrement}>-</button></div></>);
}export default App;
useMemo
组件重新渲染时缓存计算的结果。
实例:count1计算斐波那契数列,count2和count1可以触发数值变化。使用memo可以使只有在count1变化时触发斐波那契数列计算函数,而count2变化时不触发斐波那契数列计算函数。
import { useMemo } from "react";
import { useState } from "react";function fib(n) {console.log('计算函数执行')if (n < 3) {return 1}return fib(n - 1) + fib(n - 2)
}function App() {const [count1, setCount1] = useState(0)const [count2, setCount2] = useState(0)console.log('组件重新渲染')const result = useMemo(() => {return fib(count1)}, [count1])return (<div className="App"><button onClick={() => { setCount1(count1 + 1) }}>change count1: {count1}</button><button onClick={() => { setCount2(count2 + 1) }}>change count2: {count2}</button>result: {result}</div>)
}export default App
useCallback
useCallback 缓存函数
import { memo, useCallback, useState} from "react";// memo 将组件变更为记忆组件
// 如果向组件传入的 prop 没有发生变化 将不会收到外部父组件的影响
const Button = memo(function ({onClick}) {console.log('Button渲染了')return <button onClick={onClick}>点击触发子组件</button>
})function App(callback, deps) {const [count, setCount] = useState(0)// 此时不仅需要 memo 还需要将函数设为useCallback 缓存函数// 因为父组件重新渲染 那么handleClick 将被分配一块新的内存地址 和之前的不是同一个函数// eslint-disable-next-line react-hooks/exhaustive-depsconst handleClick = useCallback(() => {console.log('点击按钮')},[])const handleUpdate = () => {setCount(count + 1)}return (<><div><p>Count: {count}</p><button onClick={handleUpdate}>点击更新count</button><Button onClick={handleClick}></Button></div></>);
}export default App;