React没有提供将可复用性行为“附加”到组件的途径。(例如,把组件连接到 store)
在hook出现之前,组件复用一般采用Render Props 和 高阶组件HOC,这类方案需要重新组织你的组件结构,让代码看起来难以理解。React DevTools 中你会发现,由这些抽象层组成的组件会形成“嵌套地狱”。由此可见,React 需要为共享状态逻辑提供更好的原生途径
解决:Hook 使你在无需修改组件结构的情况下复用状态逻辑
2. 问题:组件中各种不相关的逻辑混杂
我们经常会这样,比如组件常常在 componentDidMount 和 componentDidUpdate 中获取数据,同一个 componentDidMount 中可能也包含很多其它的逻辑,如设置事件监听,而之后需在 componentWillUnmount 中清除。相互关联且需要对照修改的代码被进行了拆分,而完全不相关的代码却在同一个方法中组合在一起。
解决:Hook 将组件中相互关联的部分拆分成更小的函数
比如:使用useEffect Hook,你可以把组件内相关的副作用组织在一起(例如创建订阅及取消订阅),而不要把它们拆分到不同的生命周期函数里。同时我们又可以使用多个 Effect 实现关注点分离,将不相关的逻辑分离到了多个Effect中。
Hook 使你在非 class 的情况下可以使用更多的 React 特性。
因此,hook是为了解决一类问题出现,它让我们拥抱了函数,更灵活的让组件实现状态逻辑复用。将相关联逻辑行为更集中在更小的函数中处理。
const Fruits = () => {
const [fruits, setFruits] = useState(['苹果', '香蕉'])
const [fruit, setFruit] = useState(fruits[0])
useEffect(() => {
document.title = `你选择了${fruit}`
},[fruit])
return (
<>
<p>你最爱得水果是{fruit}</p>
<ul>
{fruits.map(f => <li key={f} onClick={()=>setFruit(f)}>{f}</li>)}
</ul>
</>
)
}
Hook 的每次调用都有一个完全独立的 state —— 因此你可以在单个组件中多次调用同一个 Hook
funciton Clock(){
const [count, setCount] = useState()
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
setCount(preC => preC + 1)
useState与class组件中的this.state的不同之处
const [count, setCount] = useState()
useEfect 告诉 React 组件需要在渲染后执行某些操作。默认情况下,它在第一次渲染之后和每次更新之后都会执行。即,总是在渲染之后执行,不用去考虑是“挂载”还是“更新”
useEffect(()=>{
const tim = setTimeout(()=>{
setCount(count + 1)
},0)
// 返回一个函数,可选的清除机制
return function clear(){
clearTimeout(tim)
}
},[count])
effect 的清除阶段在每次重新渲染时都会执行,而不是只在卸载组件的时候执行一次。
我们可以把 useEffect 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。使用它在函数中执行副作用操作。如:数据获取,设置订阅以及手动更改 React 组件中的 DOM 。
为什么React知道哪个state对应哪个useState? React 靠的是 Hook 调用的顺序,当我们将hook放入条件,循环,子函数中会让它们执行顺序不可预测,从而导致bug。
自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook
当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。
比如,实现状态管理
function useReducer(reducer, initialState) {
const [state, setState] = useState(initialState);
function dispatch(action) {
const nextState = reducer(state, action);
setState(nextState);
}
return [state, dispatch];
}
更多关于Hook的正确使用以及最佳实践,可以看React Hooks 详解 + 项目实战