不久前,react在新的16.7.0-alpha.0版本中推出了新的hooks函数,其做用就是让你能够不用类组件就可使用react的state和其余功能。你们都知道,class的写法有的时候很繁琐,好比其中的this问题等等。本篇文章主要介绍函数包括这几个useState
、useEffect
、useContext
、useRef
,这篇文章主要介绍一下这些函数的做用。javascript
好比说有一个组件须要内部维护本身的状态,以前咱们写class组件的话通常都是定义一下state,而后须要修改的时候,用setState去修改自身的状态。useState这个函数就是起到了这个做用,接受一个参数initialState
,也就是初始的state,同时返回一个数组,第一个是当前的state,第二个就是至关于之前class组件的setState,每次调用这个函数都会更新state同时让当前组件从新渲染一遍,看一下简单的count计数器用hooks怎么写html
function Cunter() {
const [count, setCount] = useState(0);
const [title, setTitle] = useState('hello-react');
console.log('render ===============');
return (
<div className="count-box"> <h1 className="title">点了{count}次</h1> <button onClick={() => { setCount(count + 1); setTitle('hello-hooks'); }}> Click Me! </button> <p>{title}</p> </div>
)
}
复制代码
上面这个组件在点击button后,打开控制台看到两次更改状态只render了一次,因此这里的useState也是会将一次循环中的state变化合并,而后一块儿更新。 同时在function组件中,useState能够调用屡次,但不意味着必定要这样写,固然,initialState能够是数组也能够是对象,因此你能够在一次set函数中直接修改像class组件中调用setState同样,不过这样写的话,我以为语义更加清晰。java
使用这个函数你能够通知react在当前组件每次渲染完成以后须要完成什么动做,我以为其做用能够理解为与以前的componentDidMount
和componentDidUpdate
两个生命周期函数相似。 这个函数支持两个参数,第一个参数是一个函数,会在每次render以后执行,同时这个函数也能够返回一个函数,这个函数会在组件卸载后执行,相似于类组件的componnentDidUnmount
生命周期函数。 举个例子,好比说咱们想实时获取窗口的宽度,而后在这个组件被卸载的时候取消这个功能。看下代码react
function Width() {
const [width,setWidth] = useState(window.innerWidth);
const setWidthFn = () => {
setWidth(window.innerWidth);
};
useEffect(() => {
window.addEventListener('resize',setWidthFn);
return () => {
window.removeEventListener('resize',setWidthFn)
}
});
return(
<div> <h1>当前窗口宽度{width}px</h1> </div>
)
}
复制代码
可是这样也有缺点,就是每次render的时候都会执行一遍这个函数,有的时候咱们并不但愿都去执行,好比说一个详情组件在第一次render的时候会跟根据props传递过来的id去取值,若是这样写的话,每一次props改变的时候都会引起组件,从新请求一遍,不过,react已经帮咱们作好了处理,咱们能够给useEffect函数传递第二个参数,****** 这样,请求详情的这个函数就只会在id改变的时候执行,因此这里的代码能够这样写。redux
function SomeComponent({id}){
useEffect(() => {
doSomethingWith(id)
/* 固然,第二个参数能够传递进不仅一个依赖项,这样就是告诉React多个依赖项有一个发生变化就会从新执行这个函数。 也能够传递进一个空数组,这样是告诉React这个函数只执行一次。 具体为何要传递进去数组,官网文档上没有看到相关的解释。 */
},[id])
}
复制代码
这个函数一样会接受一个initialState做为参数,同时返回一个对象,其中的current就是你当前传递进去的initialState,你能够把返回的对象做为ref属性,传递给子组件来获取DOM对象,同时你也能够用它来保存previousProps,用法以下:数组
function Counter() {
const [count, setCount] = useState(0);
const prevCountRef = useRef();
useEffect(() => {
prevCountRef.current = count;
});
const prevCount = prevCountRef.current;
return (
<div> <h1>Now: {count}, before: {prevCount}</h1> <button onClick={setCount(count + 1)}>Click Me!</button> </div>
)
}
复制代码
用法很简单,将React.createContext返回的结果传入useContext便可,同时context改变的时候也会引起该组件从新渲染。函数
这个函数简直和redux如出一辙了,很少介绍。学习
本来class组件中对于state的变化、修改,咱们很难能够把关于state的逻辑抽象出来,实现复用,可是基于hooks函数,你就彻底能够作到这一点。同时,React官网也说了useYourImagination,因此具体如何复用要结合实际项目进行抽离。ui
getSnapshotBeforeUpdate
和componentDidCatch
,可是不能在class函数组件中使用,同时也不建议一个项目里面二者混用,保持团队的一致性。最后引用一下Dan在React Conf上关于Hooks的演讲,简单翻译一下。this
我开始学习react的时候就想过React的logo和react有什么关系,这个项目也不叫作Atom(原子),也不是一个物理引擎,其中的一个解释是基于reaction(反应)的,化学反应就是基于原子在其中的表现,因此叫react。可是,我发现了一个更合理的解释,我以为是这样,原子的种类和属性决定了物理反应的表现和形态,react让我知道了你能够把用户界面分离成一个个独立的个体,这个个体叫作组件,这些组件的属性和种类决定了用户界面的外观和特效。但是搞笑的是,Atom这个词的自己含义就是不可分离的,当科学家们第一次发现原子的时候,他们觉得这就是最小的物质,但不久他们就发现了电子,电子就是原子中更小的一部分,电子对原子如何表现进行了更深一层的解释。我以为hooks就像是电子同样,他不是一个新的功能,他只是让我可以使用那些react已知的功能,好比说state(状态),context(上下文),life cycle生命周期函数,hooks是react一种更直接的表达方式,更好的解释了组件如何在内部工做的,我以为这些已经隐藏了长达四年久,如今你看一下react的logo,你能够看到那些电子的运动轨道,因此说hooks可能就一直存在,就像logo上的电子轨道同样。