首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

带有状态和onChange的React useMemo依赖循环

基础概念

在React中,useMemo 是一个用于优化性能的钩子(hook),它允许你在组件渲染时缓存计算结果,并且只有当依赖项发生变化时才重新计算。useMemo 接受两个参数:一个创建函数和一个依赖项数组。如果依赖项数组中的任何一个值发生变化,useMemo 将重新执行创建函数并返回新的结果。

onChange 是一个常见的事件处理器,通常用于表单元素,以便在用户输入时触发某些操作。

问题描述

当你在 useMemo 中使用带有状态的变量,并且这个变量又通过 onChange 事件处理器进行更新时,可能会遇到依赖循环的问题。这是因为每次状态更新都会导致组件重新渲染,从而触发 useMemo 的重新计算,而 useMemo 的重新计算又可能依赖于这个状态,形成一个循环。

原因分析

  1. 状态更新触发渲染:当组件的状态发生变化时,React 会重新渲染组件。
  2. useMemo 依赖项变化:如果 useMemo 的依赖项数组中包含了状态变量,那么每次状态变化都会导致 useMemo 重新计算。
  3. 循环依赖:如果 useMemo 的计算结果又影响了状态变量,这就形成了一个循环依赖。

解决方案

为了避免这种循环依赖,可以采取以下几种策略:

  1. 避免将状态直接放入依赖项数组:如果 useMemo 的计算不需要立即响应状态的变化,可以考虑移除状态变量作为依赖项。
代码语言:txt
复制
const memoizedValue = useMemo(() => {
  // 计算逻辑
}, [/* 其他依赖项,不包括状态变量 */]);
  1. 使用 useEffect 来处理状态变化:如果需要在状态变化时执行某些操作,可以使用 useEffect 钩子,并在其中调用 useMemo 的计算函数。
代码语言:txt
复制
const [state, setState] = useState(initialState);

useEffect(() => {
  // 状态变化时的操作
}, [state]);

const memoizedValue = useMemo(() => {
  // 计算逻辑
}, [/* 其他依赖项 */]);
  1. 拆分组件:将状态和 useMemo 的逻辑拆分到不同的组件中,以减少不必要的重新渲染。
代码语言:txt
复制
function ParentComponent() {
  const [state, setState] = useState(initialState);

  return <ChildComponent state={state} onChange={handleChange} />;
}

function ChildComponent({ state, onChange }) {
  const memoizedValue = useMemo(() => {
    // 计算逻辑
  }, [/* 其他依赖项 */]);

  // 使用 memoizedValue 和处理 onChange
}

示例代码

以下是一个简单的示例,展示了如何避免在 useMemo 中使用状态变量作为依赖项:

代码语言:txt
复制
import React, { useState, useMemo, useEffect } from 'react';

function MyComponent() {
  const [inputValue, setInputValue] = useState('');

  // 使用 useEffect 来响应 inputValue 的变化
  useEffect(() => {
    console.log('Input value changed:', inputValue);
  }, [inputValue]);

  // useMemo 不依赖于 inputValue
  const memoizedResult = useMemo(() => {
    // 这里是一些复杂的计算
    return inputValue.toUpperCase();
  }, [/* 其他依赖项,不包括 inputValue */]);

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
      <p>Memoized Result: {memoizedResult}</p>
    </div>
  );
}

export default MyComponent;

在这个示例中,useMemo 不再依赖于 inputValue,从而避免了依赖循环的问题。同时,我们使用 useEffect 来处理 inputValue 变化时的逻辑。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

精读《React Hooks 最佳实践》

简介 React 16.8 于 2019.2 正式发布,这是一个能提升代码质量和开发效率的特性,笔者就抛砖引玉先列出一些实践点,希望得到大家进一步讨论。...推荐使用 React.useMemo 而不是 React.memo,因为在组件通信时存在 React.useContext 的用法,这种用法会使所有用到的组件重渲染,只有 React.useMemo 能处理这种场景的按需渲染...虽然看上去 只是将更新 id 的时机交给了子元素 ,但由于 onChange 函数在每次渲染时都会重新生成,因此引用总是在变化,就会出现一个无限死循环: 新 onChange...想要阻止这个循环的发生,只要改为 onChange={this.handleChange} 即可,useEffect 对外部依赖苛刻的要求,只有在整体项目都注意保持正确的引用时才能优雅生效。...然而被调用处代码怎么写并不受我们控制,这就导致了不规范的父元素可能导致 React Hooks 产生死循环。

1.2K10

React.memo() 和 useMemo() 的用法与区别

导语 | 本文翻译自 Adebola Adeniran 在 LogRocket 论坛中关于 React.memo() 和 useMemo() 对比与用例分析。...使用 useMemo(),我们可以返回记忆值来避免函数的依赖项没有改变的情况下重新渲染。...为了在我们的代码中使用 useMemo(),React 开发者有一些建议给我们: 您可以依赖 useMemo() 作为性能优化,而不是语义保证 函数内部引用的每个值也应该出现在依赖项数组中 对于我们的下一个示例...总结:React.memo() 和 useMemo() 的主要区别 从上面的例子中,我们可以看到 React.memo() 和 useMemo() 之间的主要区别: React.memo() 是一个高阶组件...useMemo() 是一个 React Hook,我们可以使用它在组件中包装函数。我们可以使用它来确保该函数中的值仅在其依赖项之一发生变化时才重新计算。

2.7K10
  • React16之useCallback、useMemo踩坑之旅

    React.memo() React.memo也是通过记忆组件渲染结果的方式来提高性能,memo是react16.6引入的新属性,通过浅比较(源码通过Object.is方法比较)当前依赖的props和下一个...1.png 以上是一个非常简单且常见的父子组件的例子,父组件改变状态,Child组件所依赖的属性并没有更新,但是子组件每次都会重新渲染,当前例子中子组件内容较少,但如果子组件非常庞大,或者不能重复渲染的组件...父组件在更新其他状态的时候,子组件的对象属性也发生了变更,于是子组件又重新渲染了,这时候就可以使用useMemo这个hook函数。..., nextDeps]; return nextValue; } 看到主要区别了吗,useMemo把“创建”函数和依赖项数组作为参数传入,把执行结果加入缓存并返回。...也可以理解为useMemo是值对依赖项是否有依赖的缓存,useCallBack是函数对依赖项的缓存。从本质上分清二者的区别才能更清楚地感受这两个方法带来的优化。

    2.1K20

    React Hooks随记

    Hook规则 只在最顶层使用Hook,不在条件、循环或者嵌套函数中使用Hook 只在React函数式组件或自定义Hook中使用Hook 为什么Hook高度依赖执行顺序?...状态依赖(数组): 当配置了状态依赖项后,只有检测倒配置状态变化后,才会调用回调函数。...的异同 在React中,性能优化点在于: 调用setState,就会触发组件的重新渲染,不论state是否变化 父组件更新,子组件也会更新 基于以上两点,useCallback和useMemo就是解决性能问题的杀手锏...useCallback和useMemo的异同: 共同点: 仅仅是依赖数据发生变化时,才会重新计算结果,起到缓存作用。...两者区别: useMemo计算结果是return回来的值,主要用于缓存计算结果的值。应用场景: 需要计算的状态。 useCallback计算结果是函数,主要用于缓存函数。

    91720

    深入了解 useMemo 和 useCallback

    深入了解 useMemo 和 useCallback 许多人对 useMemo 和 useCallback的理解和使用都不太正确,他们都对这两个钩子感到困惑。本文中的目标就是要澄清所有这些困惑。...而 useMemo 和 useCallback 是用来帮助我们优化重渲染的工具。他们通过两种方式做到这一点: 减少在给定渲染中需要完成的工作量。 减少组件需要重新呈现的次数。...如果是,React 将重新运行提供的函数,以计算一个新的值。否则,它将跳过所有这些工作并重用之前计算的值。 useMemo 本质上类似于缓存,依赖项是缓存失效策略。...当时间状态变量发生变化时),useMemo 忽略函数并传递缓存的值。 这通常被称为记忆,这就是为什么这个钩子被称为 useMemo。...5.1 用于自定义 hook 内部 例如下面这个自定义 hook useToggle,它的工作方式几乎和 useState 完全一样,但只能在 true 和 false 之间切换状态变量: function

    9.1K30

    再探循环依赖 → Spring 是如何判定原型循环依赖和构造方法循环依赖的?

    写在前面   Spring 中常见的循环依赖有 3 种:单例 setter 循环依赖、单例构造方法循环依赖、原型循环依赖   关于单例 setter 循环依赖,Spring 是如何甄别和处理的,可查看:...问题就来了:Spring 是如何甄别单例情况下的构造方法循环依赖的,然后进行报错的   大家先把这个问题暂留在心里,我们再来看看什么是原型循环依赖   原型循环依赖   同样,我们直接看代码就明白何谓原型循环依赖了...是如何甄别单例情况下的构造方法循环依赖的     2、Spring 是如何甄别原型循环依赖的     3、为什么单例构造方法循环依赖和原型循环依赖的报错时机不一致   我们慢慢往下看,跟源码的过程可能比较快...原型类型的对象创建过程分两步:① 实例化(反射调构造方法),② 初始化(属性填充),和单例类型对象的创建过程是一样的   依赖的处理是在初始化过程中进行的, loop 对象依赖 circle 属性,所以对...  3、为什么单例构造方法循环依赖和原型循环依赖的报错时机不一致     单例构造方法实例的创建是在 Spring 启动过程中完成的,而原型实例是在获取的时候创建的     所以两者的循环依赖的报错时机不一致

    94010

    如何编写难以维护的React代码?——滥用useEffect

    如何编写难以维护的React代码?——滥用useEffect 在许多项目中,我们经常会遇到一些难以维护的React代码。其中一种常见的情况是滥用useEffect钩子,特别是在处理衍生状态时。.../*...*/} ); }; 事实上,filteredList 是一个衍生状态,可以通过计算 list 和 filter 得出:list + filter => filteredList...={setFilter} /> {/*...*/} ); }; 在改进后的代码中,我们使用了 useMemo...通过传入依赖数组 [list, filter],只有在 list 或 filter 发生变化时,才会重新计算 filteredList,从而优化性能。...减少状态的使用可以有助于降低代码的复杂性,减少潜在的错误。使用 useMemo 可以将计算逻辑从渲染过程中抽离出来,使代码更易于维护和理解。Less States, Less Bugs.

    16720

    优化 React APP 的 10 种方法

    React.PureComponent是基础组件类,用于检查状态字段和属性以了解是否应更新组件。...它将上一个道具和状态对象的字段与下一个道具和状态对象的字段进行浅层比较。它不只是对它们进行对象引用比较。 React.PureComponent通过减少浪费的渲染次数来优化我们的组件。...React.memo() 就像useMemo和React.PureComponent一样,React.memo() 用于记忆/缓存功能组件。...由于props和context是对象,因此React使用严格相等运算符===通过对象引用比较差异。因此,React使用该引用来知道先前的道具和状态何时与当前的道具和状态发生了变化。...如果再次单击该按钮,我们将有另一个重新渲染,不是这样,因为前一个状态对象和下一个状态对象将具有相同的data值,但是由于setState新状态对象的创建,React将看到差异状态对象引用和触发器重新呈现

    33.9K20

    接着上篇讲 react hook

    (() => { return doSomething(props); }); 复制代码 useState 返回的更新状态方法是异步的,下一个事件循环周期执行时,状态才是最新的值。...,而不是改一次重绘一次,也是很容易理解的.内部是通过 merge 操作将新状态和老状态合并后,重新返回一个新的状态对象,组件中出现 setTimeout 等闭包时,尽量在闭包内部引用 ref 而不是...但请不要依赖它来“阻止”渲染,因为这会产生 bug。 把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。...都是为了减少重新 render 的次数 useCallback 和 useMemo 都可缓存函数的引用或值,但是从更细的使用角度来说 useCallback 缓存函数的引用,useMemo 缓存计算数据的值...,会导致每一次加载页面引用的地址都不一样,直接导致页面死循环,所以处理的时候, 要特别小心和注意了。

    2.6K40

    React Hooks 性能优化,带你玩转 Hooks

    举个例子: 现在有个父子组件,子组件依赖父组件传入的name属性,但是父组件name属性和text属性变化都会导致Parent函数重新执行,所以即使传入子组件props没有任何变化,甚至子组件没有依赖于任何...想要解决重复渲染的问题,可以使用 react的亲手制造升级的儿子,他有三个方法用来做优化,分别是 React.memo useCallback useMemo 。...React.memo : 和 class 组件时期的 PureComponent 一样,做简单额数据类型比较 useMemo : 可以用来比较复杂类型的数据,不如 Object Array 等 useCallback...setText(e.target.value + count) },[count]) useMemo useMemo使用场景请看下面这个例子,getTotal假设是个很昂贵的操作,但该函数结果仅依赖于...count和price,但是由于color变化,DOM重新渲染也会导致该函数的执行,useMemo便是用于缓存该函数的执行结果,仅当依赖项改变后才会重新计算 const Parent = () =>

    1.6K30

    React Hook 四种组件优化

    React Hook 已成为当前最流行的开发范式,React 16.8 以后基于 Hook 开发极大简化开发者效率,同时不正确的使用 React Hook也带来了很多的性能问题,本文梳理基于 React...组件抽取 优化前 每次点击 Increase 都会引起子组件 Child 的渲染,哪怕子组件并没有状态变化 function Before(){     console.log('Demo1 Parent...,第二个为依赖值 主要用于缓存函数,第二次会返回同样的结果。...值,需要注意的是,函数内必须有返回值 第二个参数会依赖值,当依赖值更新时,会从新计算。...useCallback 和 useMemo 区别 他们都用于缓存,useCallback 主要用于缓存函数,返回一个 缓存后 函数,而 useMemo 主要用于缓存值,返回一个缓存后的值。

    15210

    React进阶篇(十)性能优化

    ,切分页面代码,减小首屏 JS 体积; React Loadable 是一个专门用于动态 import 的 React 高阶组件,你可以把任何组件改写为支持动态 import 的形式。...编译到 ES2015+,提高代码运行效率,减小体积; 使用 lazyload 和 placeholder 提升加载体验。...} } 利用useMemo缓存复杂计算的值,利用useCallback缓存函数 // useMemo // 使用useMemo来执行昂贵的计算,然后将计算值返回,并且将count作为依赖值传递进去。...当组件的状态都是不可变对象时,shouldComponentUpdate只需浅比较就可以判断状态是否真的改变,从而避免不必要的render调用。...== 'React) }) 状态类型是不可变类型 - number, string, boolean, null, undefined 状态类型是object,创建新的对象返回(Object.assign

    80720

    React 组件性能优化——function component

    甚至当依赖项增多的时候,上述两种方式将会提升代码的复杂度,我们会耗费大量的精力去思考状态的比较以及副作用的管理。...这里我们从数据缓存的层面,介绍一下函数式组件的三个性能优化方式 —— React.memo、useCallback 和 useMemo。 2. 函数式组件性能优化 2.1....假如依赖的引用数据发生了深层的变化,页面将不会得到更新,从而出现和预期不一致的 UI。...2.3. useMemo React.memo() 和 useCallback 都通过保证 props 的稳定性,来减少重新 render 的次数。...2、用一个通俗的说法去区分 React.memo 、useCallback 和 useMemo , 那大概就是: React.memo() :缓存虚拟 DOM(组件 UI) useCallback :缓存函数

    1.6K10

    React 组件性能优化——function component

    甚至当依赖项增多的时候,上述两种方式将会提升代码的复杂度,我们会耗费大量的精力去思考状态的比较以及副作用的管理。...这里我们从数据缓存的层面,介绍一下函数式组件的三个性能优化方式 —— React.memo、useCallback 和 useMemo。 2. 函数式组件性能优化 2.1....假如依赖的引用数据发生了深层的变化,页面将不会得到更新,从而出现和预期不一致的 UI。...2.3. useMemo React.memo() 和 useCallback 都通过保证 props 的稳定性,来减少重新 render 的次数。...2、用一个通俗的说法去区分 React.memo 、useCallback 和 useMemo , 那大概就是: React.memo() :缓存虚拟 DOM(组件 UI) useCallback :缓存函数

    1.6K10

    React 中 getDerivedStateFromProps 的三个场景

    React 16.3 开始,React 废弃了一些 API( componentWillMount, componentWillReceiveProps, and componentWillUpdate...根据应用场景的不同, getDerivedStateFromProps的使用方式也不同。 一、半受控组件 虽然 React 官方不推荐半受控组件,当然从 API 设计和维护的角度考虑也是不推荐的。...但是实际需求往往会出现用户不关心某个业务逻辑的内部实现,但是又希望在有需要的时候能完全控制内部的一些状态,这时候半受控组件是一个比较好的选择。...在这里,我们尽可能把控制权交给用户,只要用户传了 props就以 props的值为准,避免不同步的中间状态造成的问题。...={search} />; } } 二、带有中间状态的组件 第二种场景是一些组件需要在用户输入时有一个中间状态,当触发某个操作时再把中间结果提交给上层。

    2.3K10

    React的无状态和有状态组件

    React中创建组件的方式 在了解React中的无状态和有状态的组件之前,先来了解在React中创建组件的三种方式: ES5写法:React.createClass; ES6写法:React.Component...React.Component React.Component是以ES6的形式来创建React组件,也是现在React官方推荐的创建组件的方式,其和React.createClass创建的组件一样,也是创建有状态的组件...,高阶组件用来托管state,Redux 框架就是通过 store 管理数据源和所有状态,其中所有负责展示的组件都使用无状态函数式的写法。...有状态组件通常会带有生命周期(lifecycle),用以在不同的时刻触发状态的更新。这种组件也是通常在写业务逻辑中最经常使用到的,根据不同的业务场景组件的状态数量以及生命周期机制也不尽相同。...在React中,我们通常通过props和state来处理两种类型的数据。props是只读的,只能由父组件设置。state在组件内定义,在组件的生命周期中可以更改。

    1.5K30

    React 项目性能分析及优化

    commit 阶段:该阶段 React 会提交更新,同时在这个阶段,React 会执行像 componentDidMount 和 componentDidUpdate 之类的生命周期函数。...善用 React.useMemo React.useMemo 是 React 内置 Hooks 之一,主要为了解决函数组件在频繁 render 时,无差别频繁触发无用的昂贵计算 ,一般会作为性能优化的手段之一...React.useMemo 就是为了解决这个问题诞生的,它可以指定只有当 start 变化时,才允许重新计算新的 result 。...不像 props 和 state,React 提供了 API 进行浅比较,避免无用的 render,Context 完全没有任何方案可以避免无用的渲染。...有几点关于 Context 的建议: Context 只放置必要的,关键的,被大多数组件所共享的状态。 对非常昂贵的组件,建议在父级获取 Context 数据,通过 props 传递进来。

    1.9K20

    对比 React Hooks 和 Vue Composition API

    React Hooks 允许你 "勾入" 诸如组件状态和副作用处理等 React 功能中。Hooks 只能用在函数组件中,并允许我们在不需要创建类的情况下将状态、副作用处理和更多东西带入组件中。...默认情况下,所有用 useEffect 注册的函数都会在每次渲染之后运行,但我们可以定义真实依赖的状态和属性,以使 React 在相关依赖没有改变的情况下(如由 state 中的其他部分引起的渲染)跳过某些...useCallback 和 useMemo 也使用依赖项数组参数,以分别决定其是否应该返回缓存过的( memoized)与上一次执行相同的版本的回调或值。...React 建议你使用 useMemo 作为一个性能优化手段而非一个直到任何一个依赖项改变之前的缓存值。 作为一个补充说明:Kent C....Dodds 有一篇非常棒的文章 "useMemo 和 useCallback" 说明了很多 useMemo 和 useCallback 非必要的场景。

    6.7K30
    领券