当对一个数据的更改方式是多种多样的时,为了对数据进行统一管理,我们可以用useReducer(),比如我们想对数据增加和减少操作,我们就可以定义一个reducer函数。
import { useReducer } from 'react';
import './App.css';
// 定义一个状态 reducer 函数
function countReducer(state, action) {
switch (action.type) {
case 'increment':
// 返回当前状态 + 1
return state+1
case 'decrement':
// 返回当前状态 - 1
return state-1
default:
// 抛出错误
throw new Error()
}
}
// 定义一个组件 App
function App() {
// 使用 useReducer 初始化一个状态变量
const [state, dispatch] = useReducer(countReducer, 0);
// 定义两个函数,用于增加和减少状态
const handAdd=()=>{
dispatch({type:'increment'})
}
const handDec=()=>{
dispatch({type:'decrement'})
}
return (
<div className="App">
<div style={{padding:10}}>
<button className="btn btn-primary" onClick={handDec}>-</button>
<span>{state}</span>
<button className="btn btn-secondary" onClick={handAdd}>+</button>
</div>
</div>
);
}
export default App;
useRef()可以记住状态变更前的一个值
import { useRef, useState } from "react";
// 定义一个组件 App
function App() {
// 定义一个状态变量count,并设置初始值为0
const [count, SetCount] = useState(0)
// 定义一个响应式引用preCount,用于存储上一次的count值
const preCount = useRef()
// 定义一个函数handAdd,用于在点击按钮时更新count的值
const handAdd = () => {
// 将上一次的count值存储在preCount中
preCount.current = count
// 更新count的值
SetCount(count + 1)
}
return (
<div>
<p>最新的count:{count}</p>
<p>上次的count:{preCount.current}</p>
<button onClick={handAdd}>+1</button>
</div>
);
}
export default App;
useRef()可以引用页面中的标签进行dom操作
import { useRef } from "react";
// 定义一个组件 App
function App() {
// 定义一个输入框的引用
const inputRef = useRef(null);
// 定义一个点击事件的引用
const handClick = () => {
// 将输入框的焦点设置为第一个焦点
inputRef.current.focus();
}
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handClick}>按钮</button>
</div>
);
}
export default App;
useRef()和useForward()对子组件进行ref操作,子组件默认不对外开放dom操作,所以要用到useForwardRef。为了暴露子组件函数,需要用到useImperativeHandle()
import { forwardRef, useImperativeHandle, useRef } from "react";
const Child=forwardRef(function(prop,ref){
console.log(prop.name);
useImperativeHandle(ref,()=>({
sayHello:()=>{
console.log("Hello from child",prop.name);
}
})
)
return (
<div>Child</div>
)
})
// 定义一个组件 App
function App() {
const childRef = useRef(null);
const handClick = () => {
childRef.current.sayHello();
}
return (
<div>
<Child ref={childRef} name="Allen" />
<button onClick={handClick}>按钮</button>
</div>
);
}
export default App;
可以监听某一数据变化后,执行这个函数
import { useEffect, useState } from "react";
function App() {
// count is a state variable that stores the current count
const [count,setCount]=useState(0)
// useEffect is a hook that allows us to execute a function when the component is rendered
useEffect(() => {
console.log("useEffect called")
},[count])
// handleAdd is a function that adds 1 to the count
const handleAdd=()=>{
setCount(count+1)
}
// Return the JSX to be rendered
return (
<div>
<p>{count}</p>
<button onClick={handleAdd}>Click me</button>
</div>
);
}
export default App;
用于数据缓存的钩子,由于父组件重新渲染时,会导致子组件也重新执行,如果子组件里涉及到复杂计算时,重新执行会导致影响性能。可以用useMemo()将数据缓存起来
// 使用useMemo钩子函数,如果value参数改变,则返回result变量
const result= useMemo(()=>{
// 初始化result变量
let result=0;
// 循环计算result变量
for(let i=0;i<10000;i++){
result+=i;
}
// 返回result变量
return result;
},[value])
memo()方法可以把组件设置成记忆组件,传入的值没有变化的话,不会重新执行。
useCallback()可以缓存一个函数
cosnt handClick =useCallback(()=>{
},[])