为什么会出现Hook
- 难以复用类组件之间的逻辑
- 生命周期中经常包含一些莫名其妙的不相关逻辑
- 类组件难以被机器和人理解
React核心算法的改变
在V16版本之前 协调机制 是 Stack reconciler, V16版本发布Fiber 架构后是 Fiber reconciler。新的架构使原来同步渲染的组件现在可以异步化,可中途中断渲染,执行更高优先级的任务。
在React 16中,在dom真正render之前,React中的调度机制可能会不定期的去查看有没有更高优先级的任务,如果有,就打断当前的周期执行函数(哪怕已经执行了一半),等高优先级任务完成,再回来重新执行之前被打断的周期函数。这种新机制对现存周期函数的影响就是它们的调用时机变的复杂而不可预测,这也就是为什么在16改动生命周期的原因
为什么要改变核心算法
在Stack reconciler机制下,如果有一个很大,层级很深的组件,react渲染它需要几十甚至几百毫秒,在这期间,react会一直占用浏览器主线程,任何其他的操作(包括用户的点击,鼠标移动等操作)都无法执行。
好似一个潜水员,当它一头扎进水里,就要往最底层一直游,直到找到最底层的组件,然后他再上岸。在这期间,岸上发生的任何事,都不能对他进行干扰,如果有更重要的事情需要他去做(如用户操作),也必须得等他上岸
Fiber架构就是为了解决这个问题。
没有了生命周期,如何实现在函数组件中实现生命周期的功能
开始觉得Hook就是在函数组件中使用生命周期,越用越发现不是这么回事。Hook几乎是摒弃了生命周期的概念,useEffect一个状态足以应付,扔一篇文章https://overreacted.io/zh-hans/a-complete-guide-to-useeffect/ 由react作者写的useEffect 指南、看完对理解useEffect\hook都很有帮助
使用React.memo(Component)代替PureComponent优化性能(代替shouldComponentUpdate )
替代componentDidMount
useEffect(() => {
}, []);
替代 componentDidUpdate
const mounting = useRef(true);
useEffect(() => {
if (mounting.current) {
mounting.current = false;
} else {
fn();
}
});
替代componentWillReceiveProps中拿previousProps
function Counter() {
const [count, setCount] = useState(0);
const prevCount = usePrevious(count);
return (
<h1>
Now: {count}, before: {prevCount}
</h1>
);
}
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
替代 forceUpdate
const [ignored, forceUpdate] = useReducer(x => x + 1, 0);
function handleClick() {
forceUpdate();
}
react-router 为hook新增 ( version >= 5.0)
- useHistory
- useLocation
- useParams
- useRouteMatch
等价关系
const history = useHistory()
history.push() = this.props.history.push()
const location = useLocation()
location.state = this.props.location.state(获取不在地址栏出现的参数)
const params = useParams()
useParams().xx = this.props.match.params.xx(获取在地址栏可见的参数)
在使用router新特征时要注意先声明变量,再在函数内使用。所有use的声明都是不能放在内部函数、变量内。
useRouteMatch与上面不太像:
import { Route } from "react-router-dom";
function BlogPost() {
return (
<Route
path="/blog/:slug"
render={({ match }) => {
return <div />;
}}
/>
);
}
import { useRouteMatch } from "react-router-dom";
function BlogPost() {
let match = useRouteMatch("/blog/:slug");
return <div />;
}
可以在下面图中找到其对应的属性
react-redux为hook新增(version >= 7.1.0)
useSelector() 代替 mapStateToProps
useDispatch() 代替 mapDispatchToProps
useStore() 获取store