React Hooks实践

来源:http://www.chinese-glasses.com 作者:Web前端 人气:169 发布时间:2020-03-14
摘要:时间: 2019-12-01阅读: 38标签: Hooks function usePrevious(value) { const ref = useRef(); useEffect(() = { ref.current = value; }); return ref.current;} 这是React官网关于react使用的第一个例子,使用Hooks的方式实现了一

时间: 2019-12-01阅读: 38标签: Hooks

function usePrevious(value) { const ref = useRef(); useEffect(() = { ref.current = value; }); return ref.current;}

这是React官网关于react使用的第一个例子,使用Hooks的方式实现了一个计数器功能。useState是什么?在这里我们认为useState就是一个Hook。下面介绍 React 2个最常用的钩子,useState,useEffect。

加强版函数组件,完全不使用"类",就能写出一个全功能的组件组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来二、如何用好React-Hooks?明确几点概念所有的hook,在默认没有依赖项数组每次渲染都会更新每次 Render 时Props、State、事件处理、Effect等hooks都遵循 Capture Value 的特性Render时会注册各种变量,函数包括hooks,N次Render就会有N个互相隔离的状态作用域如果你的useEffect依赖数组为[],那么它初始化一次,且使用的state,props等永远是他初始化时那一次Render保存下来的值React 会确保 setState,dispatch,context 函数的标识是稳定的,可以安全地从 hooks 的依赖列表中省略

useEffect

七、实践场景示例

9月份开始,使用了React16.8的新特性React Hooks对项目进行了重构,果然,感觉没有被辜负,就像阮一峰老师所说的一样,这个 API 是 React 的未来。

react中性能的优化点在于:1、调用setState,就会触发组件的重新渲染,无论前后的state是否不同2、父组件更新,子组件也会自动的更新之前的解决方案

一个简单的Hook

2、用 useMemo 优化每一个具体的子节点(详见实践3)3、useCallback Hook 允许你在重新渲染之间保持对相同的回调引用以使得 shouldComponentUpdate 继续工作(详见实践3)4、useReducer Hook 减少了对深层传递回调的依赖(详见实践2)如何惰性创建昂贵的对象?当创建初始 state 很昂贵时,我们可以传一个 函数 给 useState 避免重新创建被忽略的初始 state

import React, { useState } from 'react';function Example() { // 声明一个新的叫做 “count” 的 state 变量 const [count, setCount] = useState(0); return ( div pYou clicked {count} times/p button onClick={() = setCount(count + 1)} Click me /button /div );}
const Button = React.memo((props) = { // 你的组件}, fn);// 也可以自定义比较函数

我在写React ,类组件的时候,最不愿意写的就是生命周期方法,一方面是因为生命周期方法比较多,另一方面其实也比较容易出bug。比如说,我们想要实现一个监听props的某个值的变化,进而进行一些特殊操作,就可能需要两种生命周期的方法配合。但是在Hooks里,我们只需要用到useEffect就可以实现了。

三、一句话概括Hook APIuseState 异步设置更新stateuseEffect 处理副作用(请求,事件监听,操作DOM等)useContext 接收一个 context 对象并返回该 context 的当前值useReducer 同步处理复杂state,减少了对深层传递回调的依赖useCallback 返回一个 memoized 回调函数,避免非必要渲染useMemo 返回一个 memoized 值,使得控制具体子节点何时更新变得更容易,减少了对纯组件的需要,可替代shouldComponentUpdateuseRef 返回一个在组件的整个生命周期内保持不变 ref 对象,其 .current 属性是可变的,可以绕过 Capture Value 特性useLayoutEffect 其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effectuseImperativeHandle 应当与 forwardRef 一起使用,将 ref 自定义暴露给父组件的实例值useDebugValue 可用于在 React 开发者工具中显示自定义 hook 的标签四、关注异同点useState 与 this.setState相同点:都是异步的,例如在 onClick 事件中,调用两次 setState,数据只改变一次。不同点:类中的 setState 是合并,而useState中的 setState 是替换。useState 与 useReducer相同点:都是操作state不同点:使用 useState 获取的 setState 方法更新数据时是异步的;而使用 useReducer 获取的 dispatch 方法更新数据是同步的。推荐:当 state 状态值结构比较复杂时,使用useReduceruseLayoutEffect 与 useEffect相同点:都是在浏览器完成布局与绘制之后执行副作用操作不同点:useEffect 会延迟调用,useLayoutEffect 会同步调用阻塞视觉更新,可以使用它来读取 DOM 布局并同步触发重渲染推荐:一开始先用 useEffect,只有当它出问题的时候再尝试使用 useLayoutEffectuseCallback 与 useMemo相同点:都是返回memoized,useCallback( fn, deps) 相当于 useMemo( ( ) = fn, deps)不同点:useMemo返回缓存的变量,useCallback返回缓存的函数推荐:不要过早的性能优化,搭配食用口味更佳(详见下文性能优化)五、性能优化

import { useState, useEffect } from 'react';function Example() { const [count, setCount] = useState(0); // 类似于componentDidMount 和 componentDidUpdate: useEffect(() = { // 更新文档的标题 document.title = `You clicked ${count} times`; }); return ( div pYou clicked {count} times/p button onClick={() = setCount(count + 1)} Click me /button /div );}
function App() { const [count, setCount] = useState(1); const countRef = useRef();// 在组件生命周期内保持唯一实例,可穿透闭包传值 useEffect(() = { countRef.current = count; // 将 count 写入到 ref }); // 只有countRef变化时,才会重新创建函数 const callback = useCallback(() = { const currentCount = countRef.current //保持最新的值 console.log(currentCount); }, [countRef]); return ( Parent callback={callback} count={count}/ )}function Parent({ count, callback }) { // count变化才会重新渲染 const child1 = useMemo(() = Child1 count={count} /, [count]); // callback变化才会重新渲染,count变化不会 Rerender const child2 = useMemo(() = Child2 callback={callback} /, [callback]); return (  {child1} {child2} / )}

HooksReact Hooks是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

useEffect(function persistForm() { if (name !== '') { localStorage.setItem('formData', name); }});

更新

不要在useMemo内部执行与渲染无关的操作useMemo返回一个 memoized 值,把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值,避免在每次渲染时都进行高开销的计算。传入 useMemo 的函数会在渲染期间执行,请不要在这个函数内部执行与渲染无关的操作。

useMemo把创建函数和依赖项数组作为参数传入useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。

useEffect(() = { const id = setInterval(() = { setCount(c = c + 1); }, 1000); return () = clearInterval(id);}, []);

useMemo

function useInertRef(obj) { // 传入一个实例 new IntersectionObserver(onIntersect) const ref = useRef(null); if (ref.current === null) { // ✅ IntersectionObserver 只会被惰性创建一次 ref.current = obj; } return ref.current;}

useCallback接收一个内联回调函数参数和一个依赖项数组(子组件依赖父组件的状态,即子组件会使用到父组件的值) ,useCallback 会返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。

Function Component中每次Render都会形成一个快照并保留下来,这样就确保了状态可控,hook默认每次都更新,会导致重复请求等一系列问题,如果给[]就会一尘不变,因此用好hooks最重要就是学会控制它的变化

原文:

1-2、使用useReducer解决依赖多个变量

import { useState } from 'react';function Example() { const [count, setCount] = useState(0);

在大部分情况下我们只要遵循 React 的默认行为,因为 React 只更新改变了的 DOM 节点,不过重新渲染仍然花费了一些时间,除非它已经慢到让人注意了

这个Hook,应该是我们使用最多的一个Hook了。通过在函数组件里调用它来给组件添加一些内部 state。useState方法会返回一个包含2个值的数组,第一个值是当前状态。第二个值更新这个状态的函数,它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并。我们一般会通过解构的方式获取其值。

使用immutable进行比较,在不相等的时候调用setState;在 shouldComponentUpdate 中判断前后的 props和 state,如果没有变化,则返回false来阻止更新。使用 React.PureComponent使用hooks function之后的解决方案

参考文档:React 官网

六、注意事项Hook 规则在最顶层使用 Hook只在 React 函数中调用 Hook,不要在普通的 JavaScript 函数中调用将条件判断放置在 hook 内部所有 Hooks 必须使用 use 开头,这是一种约定,便于使用 ESLint 插件 来强制 Hook 规范 以避免 Bug;

基于以上的Hook我们基本上可以完成大部分的功能了,除了上文重点介绍的useState和useEffect,react还给我们提供来很多有用的hooks useContext useReducer useRef useImperativeMethods useMutationEffect useLayoutEffect,这里就不一一介绍了,如果想要使用Hooks,这些api也是需要了解的,具体使用可以参考下面的文档。

【通过 context 往下传一个 dispatch 函数】-【createContext,useReducer,useContext】

说是新的特性,但是与其他的版本的迭代不同,它不只是加一点api减一点api的改变。而是完整的一套解决方案。

3、代码内聚,更新可控

useEffect方法接受2个参数,第一个参数是一个函数,是在第一次渲染以及之后更新渲染之后会进行的副作用,强调一点,该函数可以有返回值,但是该返回值必须是一个函数,会在组件被销毁时执行。第二个参数是可选的,是一个数组,数组中存放的是需要监听的属性。即当数组中的属性发生变化时,第一个参数的函数会被调用,如果是空数组,则在第一次渲染时会被调用。基于以上两个最主要的Hook,我们基本上可以满足于我们大部分的需求。但是如果想要对组件进行优化,则需要另外两个Hook。useCallback和useMemo。

时间: 2019-10-09阅读: 84标签: Hooks一、React-Hooks要解决什么?

这里我们将内部状态count初始化为0,在count发生变化时,会引起组件的会重新渲染。同时,我们通过解构的方式,给该状态进行了赋值。

实际应用场景往往不是一个hook能搞定的,长篇大论未必说的清楚,直接上例子(来源于官网摘抄,网络收集,自我总结)

useCallback

不要在hook内部set依赖变量,否则你的代码就像旋转的菊花一样停不下来

直接调用useState返回值的第二个参数,即可完成更新。

设计目的

使用

八、自定义 HOOK获取上一轮的 props 或 state

button onClick={() = setCount(count + 1)} Click me /button

1、使用 React.memo等效于 PureComponent,但它只比较 props,且返回值相反,true才会跳过更新

本文由10bet发布于Web前端,转载请注明出处:React Hooks实践

关键词:

最火资讯