使用hook限制
常用 hook 函数
1、useState
(1)、简单实例
在函数组件中,用 useState 实现计数器功能
import React, { useState } from 'react';
function Example() {
// 声明 `count` 的 state 变量 和 用于改变 `count` 的setCount方法;
const [count, setCount] = useState(0);
// count 和 setCount 是函数内部的变量和方法,可直接访问
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
(2) 可使用多个state
function ExampleWithManyStates() {
// 声明多个 state 变量,且他们都是相互独立的
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: '学习 Hook' }]);
(3)、函数式更新
setCount( c => c +1 )
这种方式就是函数式更新,确保了 count 更新总是建立在最新的数据上,让你从 count 的管理中解脱出来。如下实例,一个计数器,count 数值的变化,永远基于最新数值,让你不用去管理count。
function Counter({ initialCount }) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
<button onClick={() => setCount(initialCount)}>Reset</button>
<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
<button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
</>
);
}
备注:此功能用在 useEffect 中,会非常方便。
(4)、惰性初始化
useState 的初始化,可以通过传入函数的方式进行,适用于复杂计算后的结果。
const [state, setState] = useState(() => {
const initialState = someExpensiveComputation(props);
return initialState;
});
(5)、跳过 state 更新
调用 useState 的更新方法来更新state,如果新 state 数值跟之前是一样的,那么组件会跳过子组件的渲染和 useEffect 的调用。
2. 受控组件
import React, { useState } from 'react';
const Child = () => {
let [username, setUsername] = useState('')
let [password, setPassword] = useState('')
// 登录
const dologin = () => {
console.log(username, password);
}
return (
<div>
<div>
账号:
{/* 受控组件 */}
<input type="text" value={username} onChange={e => setUsername(e.target.value.trim())} />
</div>
<div>
密码:
<input type="text" value={password} onChange={e => setPassword(e.target.value.trim())} />
</div>
<div>
<button onClick={dologin}>进入系统</button>
</div>
</div>
);
}
export default Child;
3. useEffect
useEffect模拟componentDidMount
挂载时候执行
import React, { useState, useEffect } from 'react';
// 【useEffect】它是可以在函数组件中模拟出类组件中最常用的3个生命周期方法
// 它可以被调用N次
// componentDidMount componentDidUpdate componentWillUnmount
// 【注】: useEffect中不能使用async/await,useEffect执行行完要销毁,如果你返回了一个对象,则无法销毁
const Child = () => {
let [age, setAge] = useState(10)
// 模拟componentDidMount
// 参数1:回调函数,参数2:可选项,如果为一个空数组,则模拟componentDidMount
// useEffect(()=>{},[])
useEffect(() => {
console.log('模拟componentDidMount1');
}, [])
return (
<div>
<button onClick={() => setAge(age => age + 1)}>自增年龄 -- {age}</button>
</div>
);
}
export default Child;
模拟componentDidMount/componentDidUpdate
-
只写参数1:回调函数
全局的数据更新都会触发它
-
指定state数据更新才触发,必须写参数2,依赖项
写多个参数
模拟componentDidMount/componentWillUnmount
挂载时候执行,组件销毁执行
模拟componentDidMount/componentDidUpdate/componentWillUnmount
挂载时候执行,数据更新时它会执行,组件销毁执行
网络请求
第一种写法
第二种写法:
第三种写法
import { useState, useEffect } from 'react';
import { getSwiperApi } from '@/api'
const useHttpSwiper = () => {
let [data, setData] = useState([])
const loadData = async () => {
let ret = await getSwiperApi()
setData(data => [...data, ...ret.data])
}
// useEffect它不能使用async/await
useEffect(() => {
loadData()
}, [])
return [
data,
loadData
]
}
export default useHttpSwiper
import useHttpSwiper from "@/hooks/useHttpSwiper";
const Child = () => {
let [data, loadData] = useHttpSwiper()
return (
<div>
{
data.map((item, index) => (
<li key={index}>{item.title}</li>
))
}
<hr />
<button onClick={() => loadData()}>加载更多数据</button>
</div>
);
}
export default Child;
4. useReducer
useReducer 这个 Hooks 在使用上几乎跟 Redux一模一样,唯一缺少的就是无法使用 redux 提供的中间件。
import React, { useReducer } from 'react';
// useReducer可以理解为,精简版的redux,写法和redux一致
const initState = {
count: 100
}
const reducer = (state, { type, data }) => {
if ('add' === type) return { ...state, count: state.count + data }
return state
}
const Todo = () => {
// 参数1:纯函数,用来完成state数据的修改
// 参数2:初始数据
// 参数3:惰性初始数据,如果有参数3,则参数2,无效了 回调函数,要返回一个对象
let [state, dispatch] = useReducer(reducer, initState)
return (
<div>
<h3>{state.count}</h3>
<button onClick={() => dispatch({ type: 'add', data: 2 })}>++++</button>
</div>
);
}
export default Todo;
使用useReducer完成todolist
src/App.jsx
src/Todo/reducer.js
src/Todo/index.jsx
src/Todo/ui/Todoform.jsx
src/Todo/ui/Todoitems.jsx
src/hooks/userInput.js
5. useContext
App.js
src/context/app.js
child.jsx
6. useMemo
记忆组件,可以理解为计算属性 性能优化
7.useCallback
记忆函数,它计算返回一个缓存函数。
8. React.memo
给函数组件来减少重复渲染的顶层Api,类似于PureComponent