Hooks 要解决的问题
组件之间的逻辑复用
现有的常用方案是 render props 和 higher-order components ,同时也带了问题: 重新调整组件结构
逻辑调用链长,难以理解
形成组件的嵌套地狱
复杂组件难以理解
组件越来越复杂:
初期简单的类组件随着功能的增多变得越来越复杂,也越来越难以拆分
生命周期机制把相关的代码分离在不同的部分,把不相关的代码又合在一起,容易引入bug
引入各种各样的库,提升项目复杂度
类组件的冗杂
类组件有许多不方便之处: this
绑定事件处理程序
代码冗长
......
Hooks 核心思想
减少组件嵌套,聚合相关逻辑,抽取细粒度的可复用组件
Hooks 核心 API
useState(initialState)
import React, { useState } from 'react'
function Count() {
const [count, setCount] = useState(0)
const [lazyState, setLazyState] = useState(() => expensiveComputation())
return (
<div>
<p>lazy state {lazyState}</p>
<p>you clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
</div>
)
}
useEffect(fn, [dependencyList])
import React, { useState, useEffect } from 'react'
function List() {
const [dataList, setDataList] = useState([])
const [searchValue, setSearchValue] = useState('123')
useEffect(() => {
consoloe.log(searchValue)
})
useEffect(() => {
async function fetchData(value) {
const result = await fetch('xxx')
setDataList(result.data);
}
fetchData(searchValue)
}, [searchValue])
useEffect(() => {
function scroll() {
/* ... */
}
window.addEventListener('scroll', scroll)
return () => {
window.removeEventListener('scroll', scroll)
}
}, [])
return (
<div>
<input
value={searchValue}
onChange={e => setSearchValue(e.target.value)}
/>
<ul>
<li>
{dataList.map((data, index) => <li key={index}>{data.text}</li>)}
</li>
</ul>
</div>
)
}
useLayoutEffect(fn, [dependencyList])
同步版的 useEffect,常用于 dom 更新时的元素位置、样式等属性的计算
Hooks 附加 API
useReducer(reducer, initialState)
import React, { useState, useReducer } from 'react'
/* base implements */
function useReducer(reducer, initialState) {
const [state, setState] = useState(initialState)
function dispatch(action) {
const newState = reducer(state, action)
setState(newState)
}
return [state, dispatch]
}
function reducer(state = 0, action) {
switch(action.type) {
case 'increase': return state - 1
case 'decrease': return state + 1
default: return state
}
}
function Count() {
const [count, dispatch] = useReducer(reducer, 0)
return (
<div>
<p>you clicked {count} times</p>
<button onClick={() => dispatch({action: 'increase'})}>+</button>
<button onClick={() => dispatch({action: 'decrease})}>-</button>
</div>
)
}
useCallback(fn, [dependencyList])
import React, { useState, useCallback, memo } from 'react'
const Button = memo(props => {
useEffect(() => {
console.log('rendered')
})
return (
<button onClick={props.onClick}>{props.children}</button>
)
})
function Counter({initialCount = 0}) {
const [count, setCount] = useState(initialCount);
const memoClick = useCallback(() => {
setCount(prevCount => prevCount + 1)
}, [])
return (
<>
Count: {count}
<Button onClick={memoClick}>+</Button>
<Button onClick={() => setCount(count - 1)}>-</Button>
</>
);
}
useMemo(() => fn, [dependencyList])
import React, { useState, useCallback, useMemo } from 'react'
function Counter({initialCount = 0}) {
const [count, setCount] = useState(initialCount);
// useCallback(fn, deps) is equivalent to useMemo(() => fn, deps)
const memoClick = useMemo(() => () => {
setCount(prevCount => prevCount + 1)
}, [])
/*...*/
}
useRef(initialValue)
import React, { useRef } from 'react'
function TextInputWithFocusButton() {
const inputEl = useRef(null)
const onButtonClick = () => {
inputEl.current.focus()
}
return (
<>
<input ref={inputEl} type="text" />
<button onClcik={onButtonClick}>Focus the input</button>
</>
)
}
function Button() {
const count = useRef(null)
return (
<button>rendered {count.current++} times</button>
)
}
Hooks 推荐规则
Only Call Hooks at the Top Level
Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function.
Only Call Hooks from React Functions
Call Hooks from React function components. Call Hooks from custom Hooks
延伸阅读
Hooks API Reference
Hooks FAQ
useEffect 完整指南
如何错误使用useCallback
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!