使用规则
只能在组件中或者其他自定义的Hook函数中调用
只能在组件的顶层调用,不能嵌套在if
、for
、 其他函数中
基础Hook 函数
useState
useState
是一个hook
函数,它允许我们向组件中添加一个状态变量,从而控制影响组件的渲染结果
示例1
function App() {
// 创建一个状态变量
// count: 状态变量,setCount: 更新状态变量的函数
const [count, setCount] = useState(0)
return (
<div>
<p>当前数值是:{count}</p>
<button onClick={() => setCount(count + 1)}>加一</button>
</div>
)
}
示例2
function App() {
const [userName, setUserName] = useState("111");
return (
<div>
<input
type="text"
value={userName}
placeholder="请输入"
onChange={(e) => setUserName(e.target.value)}
/>
<div>当前输入值是:{userName}</div>
</div>
);
}
注意:
- 在
react
中,状态被认为是只读的,直接修改状态不能引发视图的更新 - 对于对象类型的状态变量,应该始终传给
set
方法一个全新的对象来进行修改
function App() {
const [form, setForm] = useState({
age: 0
})
return (
<div>
<p>当前年龄是:{form.age}</p>
<button onClick={() => setForm({
...form,
age: form.age + 1
})}>加一</button>
</div>
)
}
useRef
获取、操作DOM
function App() {
// 使用 useRef生成ref对象,并绑定到dom上
const inputRef = useRef(null);
// 获取dom
const getDom = () => {
console.log(inputRef.current);
};
return (
<div>
<input type="text" ref={inputRef} placeholder="请输入" />
<button onClick={getDom}>获取dom</button>
</div>
);
}
useEffect
useEffect
是一个React Hook
函数,用于在React
组件中创建不是由事件引起而是由渲染本身引起的操作,比如发送AJAX
请求、更改DOM
等
function App() {
const [content, setContent] = useState("");
const [note, setNote] = useState("");
useEffect(() => {
// 获取每日英语
function getEnglish() {
fetch("https://api.oioweb.cn/api/common/OneDayEnglish")
.then((res) => res.json())
.then((data) => {
console.log(data);
setContent(data.result.content);
setNote(data.result.note);
});
}
getEnglish();
}, []);
return (
<div>
<div>英文:{content}</div>
<div>翻译:{note}</div>
</div>
);
}
不同依赖项说明
- 没有依赖项,组件初始渲染+组件更新时执行
- 空数组依赖,只在初始渲染时执行一次
- 添加特定依赖项,组件初始渲染+特性依赖项变化时执行
没有依赖项
function App() {
const [content, setContent] = useState(0);
useEffect(() => {
console.log("副作用执行了");
});
return (
<div>
<button onClick={() => setContent(content + 1)}>{content}</button>
</div>
);
}
空数组依赖
function App() {
const [content, setContent] = useState(0);
useEffect(() => {
console.log("副作用执行了");
}, []);
return (
<div>
<button onClick={() => setContent(content + 1)}>{content}</button>
</div>
);
}
特性依赖变化
function App() {
const [content, setContent] = useState(0);
useEffect(() => {
console.log("副作用执行了");
}, [content]);
return (
<div>
<button onClick={() => setContent(content + 1)}>{content}</button>
</div>
);
}
清除副作用
在useEffect
中编写的由渲染本身引起的对接组件外部的操作, 社区也叫做副作用操作,比如在useEffect
中开启了一个定时器,我们想在组件卸载时把这个定时器再清理掉,这个过程就是清除副作用。
useEffect(() => {
console.log("副作用执行了");
return () => {
console.log("清除副作用");
};
}, []);
清除副作用的函数最常见的执行时机是在组件卸载时自动执行。
function App() {
const [show, setShow] = useState(true);
return (
<div>
父组件
<button onClick={() => setShow(false)}>卸载Son组件</button>
{show && <Son />}
</div>
);
}
function Son() {
const [currentDate, setCurrentDate] = useState("");
useEffect(() => {
const timer = setInterval(() => {
const newDate = new Date().toLocaleTimeString();
setCurrentDate(newDate);
console.log("当前时间:", newDate);
}, 1000);
return () => {
// 不清除副作用,即使组件不适用了,定时器还会执行
clearInterval(timer);
};
}, []);
return (
<div>
<div>子组件</div>
<div>当前时间是:{currentDate}</div>
</div>
);
}
自定义Hook
自定义Hook是以use
打头的函数,通过自定义Hook函数可以用来实现逻辑的封装和复用
function App() {
const [state, toggle] = useToggle()
return (
<div>
{ state && <div>这是一个div</div> }
<button onClick={toggle}>切换</button>
</div>
)
}
function useToggle(){
// 可复用的逻辑代码
const [state, setState] = useState(true)
const toggle = () => {
setState(!state)
}
// 那些状态和方法需要在其他组件中使用,则返回
return [state, toggle]
}
通用思路
- 声明一个以
use
大头的函数 - 在函数体内封装可以复用的逻辑
- 将组件中用的的状态或者回调函数return出去(对象或者数组形式)
- 在那个组件中用到这个逻辑,就执行这个函数,结构出来状态和回调进行使用
function App() {
const [content, note] = useOneDayEnglish();
return (
<div>
<div>英文:{content}</div>
<div>翻译:{note}</div>
</div>
);
}
function useOneDayEnglish() {
const [content, setContent] = useState("");
const [note, setNote] = useState("");
useEffect(() => {
// 获取每日英语
function getEnglish() {
fetch("https://api.oioweb.cn/api/common/OneDayEnglish")
.then((res) => res.json())
.then((data) => {
console.log(data);
setContent(data.result.content);
setNote(data.result.note);
});
}
getEnglish();
}, []);
return [content, note];
}