React Hooks 是React 16.7.0-alpha 版本推出的新特性。从 16.8.0 开始,React更稳定的支持了这一新特性。html
它可让你在不编写 class 的状况下使用 state 以及其余的 React 特性。react
注意:React 16.8.0 是第一个支持 Hook 的版本。升级时,请注意更新全部的 package,包括 React DOM。React Native 将在下一个稳定版本中支持 Hook。redux
若是说promise是JavaScript异步的终极解决方案,那么React Hooks从某种意义上来讲,也是react状态管理的终极解决方案。数组
在react hooks,react态管理方案主要有以下2种:promise
这两种状态解决方案其实已经很不错,能够知足绝大多数状态共享的业务场景。 固然,像FB这样优秀的团队优秀的人总喜欢钻研,不断优化。认为这两种状态解决方案嵌套太多,不少业务逻辑能够抽象出来。不只仅是共享状态就完事了,还得共享出处理逻辑。为了减小没必要要的组件嵌套写法,实现更扁平、颗粒化的状态 + 逻辑的复用,因而便推出了 React Hooks。bash
关于react hooks,具体能够多看看React Hooks官方文档,理解会更深。异步
一、基于 render-props实现:函数
// 将父组建的 on状态 和toggle 事件,共享给嵌套下的子组件
function App() {
return (
<Toggle initial={false}>
{({ on, toggle }) => (
<Button type="primary" onClick={toggle}> Open Modal </Button>
<Modal visible={on} onOk={toggle} onCancel={toggle} />
)}
</Toggle>
)
}
复制代码
二、用react hooks实现学习
import React, { useState } from 'react';
function Example() {
// 声明一个新的叫作 “visible” 的 state 变量
const [visible, setVisible] = useState(false);
return (
<div>
<Modal onClick={() => setVisible(!visible)}>
Click me
</Modal>
</div>
);
}
复制代码
function Avatar(props) {
const [user, setUser] = React.useState({...props.user}); // 这里仅仅是给了一个初始值,仅第一次渲染的时候生效,后续都不会再更新了。
// 用useEffect,第二个参数传入一个数组字段props.user,
// 表示每次只要传入的props.user有变化,那么就触发setUser这个操做更新状态。
React.useEffect(() => {
setUser(props.user);
}, [props.user])
return user.avatar ?
(<img src={user.avatar}/>)
: (<p>Loading...</p>);
}
复制代码
由上述例子能够看到,咱们用到了useEffect这个hooks。优化
Effect Hook 可让你在函数组件中执行反作用操做
什么叫反作用呢? 数据获取,设置订阅以及手动更改 React 组件中的 DOM 都属于反作用。
若是实在理解不了反作用,你能够理解为,在咱们在写传统的react class组件里面的生命周期钩子函数componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合中处理的相关逻辑,就是反作用。
也就是说,任何你想在页面首次加载完(componentDidMount),后续每次更新完(componentDidUpdate),亦或者是组件卸载前(componentWillUnmount),这三个勾子中加入你本身的逻辑处理,就得用到useEffect
业务场景具体以下:实现一个倒计时30秒,每秒钟减1,而后倒计时完毕这个组件自动隐藏。
function App() {
const [count, setCount] = useState(30);
useEffect(() => {
setInterval(() => {
setCount(count - 1);
}, 1000);
});
return <div className="App">{count}</div>;
}
复制代码
看看上述的写法,本身运行一下就只知道了,确定是大错特错的。 最基本的,setInterval这个删除定时器都没有作相关处理。 其次,每次都会生成不一样都setInterval实例。那么如何加以控制呢?
来看看正确都写法,这里要用到useRef这种类型都hooks了。
function App(props){
const [visible,setVisible] = useState(false);// 初始化值为false,隐藏
const [count,setCount] = useState(0); // 倒计时字段,初始值为0
// 明肯定时器要作什么:咱们这里是每秒 -1,小于等于0的时候就自动给隐藏
// 同时,本此的跟新跟下次的渲染更新要共享状态,记住上次更新这个count减到哪里了
// 基于上述问题,咱们可使用以下方案:
// 声明一个useRef对象,初始化为null
const intervalCb = useRef(null);
useEffect(()=>{
// useRef 对象有一个current属性,能够给它赋值为一个函数
intervalCb.current = () => {
if(count <= 0){
setVisible(false);
}else{
setCount(count - 1);
}
};
})
// 在componentDidMount中设置一个定时器
useEffect(()=>{
function itvFn(){
// 在此前,定时器的回调函数已经声明,这里能够直接调用
intervalCb.current();
}
const itvId = window.setInterval(itvFn,1000);
// return 一个回调函数,表示清除处理
return () => window.clearInterval(itvId);
},[]) // 传入要监听的对象,空数组表示只监听一次,至关于didMounted
}
return (<div className={visible}>
{count}
</div>)
}
复制代码
关于useRef 更多的请看useRef官方文档
基于上述setInterval的业务功能实现,咱们简单的来写一个自定义的hooks
export default function useInterval(callback) {
const savedCallback = useRef();
useEffect(() => {
savedCallback.current = callback;
});
useEffect(() => {
function tick() {
savedCallback.current();
}
let id = setInterval(tick, 1000);
return () => clearInterval(id);
}, []);
}
复制代码
而后在你须要用到的地方引入:
import useInterval from 'xx/self_hooks';
function App(){
useInterval(()=>{
// ... 跟useEffect写法相似,目前只支持传入一个function类型的参数,若是要接收多个参数,那么在自定义hooks那里去自行处理一下。
})
}
复制代码
关于自定义hooks,更多请查看自定义hooks
关于react hooks 简单的使用,此篇就暂时写到这里,固然,复杂一点的,可使用useReducer、useContext和useEffect代替Redux方案。后续咱们应该单独来研究这块。 回顾一下,如何才能说咱们会用react hooks 呢?
今天先把问题抛出,后续按照这个,按部就班的学习掌握react hooks。