本文主要讲以下内容: 函数式组件和类组件的不同 React Hooks依赖数组的工作方式 如何在React Hooks中获取数据 一、函数式组件和类组件的不同 React Hooks由于是函数式组件...我们组件第一次渲染的时候,从useState()拿到num的初始值为0,当我们调用setNum(1),React会再次渲染组件,这一次num是1。...setTimeout(() => { alert(num); }, 3000); // ... } 在我们更新状态之后,React会重新渲染组件。...(其实这些归根究底,就是React Hooks会形成闭包) 三、如何在React Hooks中获取数据 在我们用习惯了类组件模式,我们在用React Hooks中获取数据时,一般刚开始大家都会这么写吧:...并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数。
在函数组件主体内(这里指在 React 渲染阶段)改变 DOM、添加订阅、设置定时器、记录日志以及执行其他包含副作用的操作都是不被允许的,因为这可能会产生莫名其妙的 bug 并破坏 UI 的一致性。...赋值给 useEffect 的函数会在组件渲染到屏幕之后执行。你可以把 effect 看作从 React 的纯函数式世界通往命令式世界的逃生通道。(官方文档) 这么一看你也许会有点不明白......通过使用这个 Hook,你可以告诉 React 组件需要在渲染后执行某些操作。React 会保存你传递的函数(我们将它称之为 “effect”),并且在执行 DOM 更新之后调用它。...运行所有生命周期函数和 ref 回调函数。生命周期函数会在一个独立的通道中运行,所以整个组件树中所有的替换、更新、删除都会被调用。这个过程还会触发任何特定于渲染器的初始 effect hook。...create —— 绘制之后运行的回调函数 destroy —— 它是 create() 返回的回调函数,将会在初始渲染前运行 inputs —— 一个集合,该集合中的值将会决定一个 effect 节点是否应该被销毁或者重新创建
一、 Hook 简介 1.1 Hook历史 在React Hook出现之前的版本中,组件主要分为两种:函数式组件和类组件。...useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。...那useMemo 是如何使用的呢,看下面的一个例子。...比如,在React 中我们经常会面临子组件渲染优化的问题,尤其在向子组件传递函数props时,每次的渲染 都会创建新函数,导致子组件不必要的渲染。...,我们通过 useImperativeHandle 将子组件的实例属性输出到父组件,而子组件内部通过 ref 更改 current 对象后组件不会重新渲染,需要改变 useState 设置的状态才能更改
,在组件渲染完监听 hashchange ,回调函数是拿不到后续更新的 state 的,只能能到初始化时候的空字符串。...的作用,返回一个缓存的函数,在函数组件里面,每次渲染都会执行一次组件函数,组件函数每次执行,在组件内部的函数都会重新定义,这样的话,父组件传给子组件的回调函数每次渲染都会变再从 memo 的角度去看,...父组件每次渲染,子函数组件如果不加 memo 的话,就算是子组件无任何依赖,属性都不变的情况下,子组件也会重新渲染如果在父组件单独加为子组件的回调函数添加 useCallback,这样可以避免回调函数重新定义...,但是子组件如果不用 memo 包裹,就算任何子组件属性没改变,还是会导致子组件重新渲染;同样的,如果子组件单独用 memo 包裹,父组件每次渲染,重新定义回调函数,还是会导致重新所以,memo 和 useCallback...和 React.useMemoReact.momo 在防止子组件重新渲染方面,是最简单的,在类组件里面有个 React.PureComponent,其作用也是。
portals的使用 portals存在的意义在于,有时候我们想要一个组件独立于父组件进行渲染,例如这样的一个场景:父组件的显示区域比较小,但是我们想要一个组件显示在屏幕的中间,此时就可以使用portals...class组件有自己的生命周期,函数式组件则会每次重新渲染都重新发送一次网络请求。 函数式组件在重新渲染时整个函数都会被执行。...show)}>点击切换 ) } useMemo还可以避免子组件不必要的重新渲染。...(结合了memo) const MyButton = memo(props => { console.log('子组件重新渲染'); return ( 子组件收到的props:{...ref获取到子组件的所有权限,通过useImperativeHandle可以让子组件指定对外暴露的功能。
如何让 Function Component 也打印 3 3 3? 所以这是不是代表 Function Component 无法覆盖 Class Component 的功能呢?...它的返回值是一个函数,这个函数在 useEffect 即将重新执行时,会先执行上一次 Rerender useEffect 第一个回调的返回函数,再执行下一次渲染的 useEffect 第一个回调。...然而对这个例子而言,代码依然存在 BUG:每次计数器都会重新实例化,如果换成其他费事操作,性能成本将不可接受。 如何不在每次渲染时重新实例化 setInterval?...所以 useReducer 也被称为解决此类问题的 “黑魔法”。 其实不管被怎么称呼也好,其本质是让函数与数据解耦,函数只管发出指令,而不需要关心使用的数据被更新时,需要重新初始化自身。...不仅解决了维护性问题,而且对于 只要参数变化,就重新执行某逻辑,是特别适合用 useEffect 做的,使用这种思维思考问题会让你的代码更 “智能”,而使用分裂的生命周期进行思考,会让你的代码四分五裂,
portals的使用portals存在的意义在于,有时候我们想要一个组件独立于父组件进行渲染,例如这样的一个场景:父组件的显示区域比较小,但是我们想要一个组件显示在屏幕的中间,此时就可以使用portals...在Hook出现之前,函数式组件相对于class组件有如下劣势:class组件可以定义自己的状态,函数式组件不可以。class组件有自己的生命周期,函数式组件则会每次重新渲染都重新发送一次网络请求。...函数式组件在重新渲染时整个函数都会被执行。...show)}>点击切换 )}useMemo还可以避免子组件不必要的重新渲染。...,通过useImperativeHandle可以让子组件指定对外暴露的功能。
注意 React 会确保 setState 函数的标识是稳定的,并且不会在组件重新渲染时发生变化。...不过由于 React 不会对组件树的“深层”节点进行不必要的渲染,所以大可不必担心。如果你在渲染期间执行了高开销的计算,则可以使用 useMemo 来进行优化。...默认情况下,effect 将在每轮渲染结束后执行,但你可以选择让它 在只有某些值改变的时候 才执行。 清除 effect 通常,组件卸载时需要清除 effect 创建的诸如订阅或计时器 ID 等资源。...并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。...将来,React 可能会选择“遗忘”以前的一些 memoized 值,并在下次渲染时重新计算它们,比如为离屏组件释放内存。
为了防止引起内存泄露,在 class 组件中,会在 componentDidMount 添加的事件监听,然后在 componentWillUnmount 生命周期中移除事件监听,但这样会让处理同一个功能逻辑的代码分布在两个不同的地方...而在函数组件中 useEffect 的处理方式就高明许多,useEffect 设计是让属于同一副作用的代码在同一个地方执行。...调用了 useContext 的组件总会在 context 值变化时重新渲染。...当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。...这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。 只在 React 函数中调用 Hook。
在React v16.8新增了Hook,它提供了在函数组件中访问状态和React生命周期等能力,这些函数可以在程序的各个组件之间复用,达到共享逻辑的目的。...当状态被更新时,它会触发组件的重新渲染。...我们可以让useEffect 接受一个回调作为参数,并且这个回调可以返回一个清理函数。...当我们从子组件中传出一个回调时,这个hook可以被用来避免没有意义的渲染。因为这个回调只有在数组里的值改变的时候才会被执行,我们可以借此优化我们的组件。...一旦状态更新,它就会传递给正在使用这个hook的组件,导致其重新渲染。 我们的这个hook可以在任意的函数组件中使用,因为我们给它增加了类型定义, 使用它的组件默认都会拿到它的类型定义。
学习如何轻松构建可伸缩的 React 应用程序:Ract Hooks # React Hooks React Hooks 是在函数式组件中使用的生命周期方法,React Hooks 在 React 16.8...在 React 中,当父组件重新渲染时,所有的子组件也会重新渲染。如果子组件的某个函数作为 props 传递给子组件,而父组件重新渲染时,这个函数会被重新创建。...当依赖项数组中的任何一个值发生变化时,回调函数就会重新生成。这意味着当 useCallback 返回的函数被传递给子组件时,只有在依赖项变化时才会重新生成。...,该变量的值在组件重新渲染时不会被重置。...useContext 接受一个上下文对象(通过 React.createContext 创建),并返回该上下文的当前值。在组件渲染期间,当上下文的值发生更改时,React 将重新渲染组件。
这样的话,一旦 effect 的依赖发生变化,它就会被重新创建。在某些情况下,我们不需要在每次组件更新时都创建新的订阅,而是仅需要在 source prop 改变时重新创建。...并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。...state 相同,React 将跳过子组件的渲染及副作用的执行。...你可以把 useMemo 作为性能优化的手段,但不要把它当成语义上的保证。将来,React 可能会选择“遗忘”以前的一些 memoized 值,并在下次渲染时重新计算它们,比如为离屏组件释放内存。...它可以很方便地保存任何可变值,其类似于在 class 中使用实例字段的方式。请记住,当 ref 对象内容发生变化时,useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。
② 第二个参数 有时候,我们不希望 useEffect() 每次渲染都执行,这时可以使用它的第二个参数,使用一个数组指定副作用函数的依赖项,只有依赖项发生变化,才会重新渲染。...因此,副作用函数这时只会在组件加载进入 DOM 后执行一次,后面组件重新渲染,就不会再次执行。...) 下面是从远程服务器获取数据的例子: import React, { useState, useEffect } from 'react' import axios from 'axios' function...拿到数据以后,再用 setData() 触发组件的重新渲染。 由于获取数据只需要执行一次,所以上例的 useEffect() 的第二个参数为一个空数组。...实际使用中,由于副作用函数默认是每次渲染都会执行,所以清理函数不仅会在组件卸载时执行一次,每次副作用函数重新执行之前,也会执行一次,用来清理上一次渲染的副作用。
useState就是用来解决这个问题的,它允许Function Component将自己的状态持久化到React运行时(runtime)的某个地方(memory cell),这样在组件每次重新渲染的时候都可以从这个地方拿到该状态...这里要注意的是虽然React不会渲染子组件,不过它还是会重新渲染当前的组件的,如果你的组件渲染有些很耗性能的计算的话,可以考虑使用useMemo来优化性能。...当开发者在定义Function Component的时候往往需要在函数体内定义一些内嵌函数(inline function),这些内嵌函数会在组件每次重新渲染的时候被重新定义,如果它们作为props传递给了子组件的话...,由于这个组件需要渲染一个大的列表(items),所以每次重渲染都是十分消耗性能的,因此我使用了React.memo函数来让该组件只有在onClick函数和items数组发生变化的时候才被渲染,如果大家对...context,让它们的职责更加分明,这样子组件只会订阅那些它们需要订阅的context从而避免无用的重渲染。
这样就把计算逻辑独立在 useReducer 外部,为将来对重置 state 的 action 做处理提供了便利。...如果 useReducer 返回的 state 相比于之前没有变化,React会自动跳过对组件的渲染操作。...--- 四、解决层层回调的烦恼 1、useContext + useReducer 顶层组件有个回调函数要传递下去,需要每一层都使用 props 进行设置,很繁琐,这里可以用 useContext +...const TodosDispatch = React.createContext(null); function TodosApp() { // 提示:`dispatch` 不会在重新渲染之间变化...的Reducer Hook让state有了状态!
当 ThemeContext 更新时,组件会重新渲染,并使用最新的 context 值。...4. useReducer useReducer 是另一个可以在函数组件中保存 state 的 Hook,但它更适用于有复杂 state 逻辑的组件,它接受一个 reducer 函数和初始 state...5. useCallback useCallback 返回一个记忆化版本的回调函数,它仅在依赖项改变时才会更新。当你将回调传递给被优化的子组件时,它可以防止因为父组件渲染而无谓的渲染子组件。...这样,只有当 increment 函数改变时,Button 组件才会重新渲染。 6. useMemo useMemo 返回一个记忆化的值。它仅在某个依赖项改变时才重新计算 memoized 值。...这使得你在没有写 class 的情况下可以直接在你的函数组件中使用这些特性。 总的来说,Hooks 是一种强大的工具,它使我们能够在函数组件中使用 React 的各种特性。
以前在 React 中,共享逻辑的方法是通过高阶组件和 props 渲染。Hooks 提供了一种更简单方便的方法来重用代码并使组件可塑形更强。...本文将展示 TypeScript 与 React 集成后的一些变化,以及如何将类型添加到 Hooks 以及你的自定义 Hooks 上。...当提供程序更新时,此挂钩将触发使用最新上下文值的重新渲染。...当您将回调函数传递给子组件时,将使用此钩子。这将防止不必要的渲染,因为仅在值更改时才执行回调,从而可以优化组件。可以将这个挂钩视为与shouldComponentUpdate生命周期方法类似的概念。...useMemo 只会在其中一个依赖项发生更改时重新计算 memoized 值。此优化有助于避免在每个渲染上进行昂贵的计算。
render函数等) 3 react-hooks可能把庞大的class组件,化整为零成很多小组件,useMemo等方法让组件或者变量制定一个适合自己的独立的渲染空间,一定程度上可以提高性能,减少渲染次数...useState和useReduce 作为能够触发组件重新渲染的hooks,我们在使用useState的时候要特别注意的是,useState派发更新函数的执行,就会让整个function组件从头到尾执行一次...无状态组件中的redux useReducer 是react-hooks提供的能够在无状态组件中运行的类似redux的功能api,至于它到底能不能代替redux react-redux ,我个人的看法是不能的...和新的goodList 是否相等,如果相等, 则不更新此组件 这样就可以制定属于自己的渲染约定 ,让组件只有满足预定的下才重新渲染 */ }, (pre, next) => is(pre.goodList...,useCallback返回的是函数,这个回调函数是经过处理后的也就是说父组件传递一个函数给子组件的时候,由于是无状态组件每一次都会重新生成新的props函数,这样就使得每一次传递给子组件的函数都发生了变化
领取专属 10元无门槛券
手把手带您无忧上云