简体   繁体   English

在 Firefox 中反应性能问题?

[英]React Performance Issues in Firefox?

I'm experiencing some performance issues with a react application that I developed.我开发的反应应用程序遇到了一些性能问题。 These issues specifically (or most notably) occur with Firefox (both FF developer 77.0b7 and FF 76.0.1).这些问题在 Firefox(FF 开发人员 77.0b7 和 FF 76.0.1)中特别出现(或最明显)。

When using this application in Firefox, CPU usage gets extremely high, and my fans start spinning up to very high speeds.在 Firefox 中使用此应用程序时,CPU 使用率变得非常高,我的风扇开始以非常高的速度旋转。 I get about 15-19fps in firefox according to the performance tools in FF.根据 FF 中的性能工具,我在 firefox 中得到大约 15-19fps。 I get roughly 60fps in Chrome and Safari.我在 Chrome 和 Safari 中获得大约 60fps。

These issues occur when I begin typing into the input field, and get worse as the input gets longer (which makes sense)当我开始在输入字段中输入时会出现这些问题,并且随着输入变长而变得更糟(这是有道理的)

The application is available here: https://text-to-aura-generator.netlify.app/该应用程序可在此处获得: https://text-to-aura-generator.netlify.app/

Source code available here: https://github.com/paalwilliams/Text-to-Aura/tree/master/src此处提供源代码: https://github.com/paalwilliams/Text-to-Aura/tree/master/src

I'm almost certain that this is something I'm doing incorrectly, or that I've written the code inefficiently, but that isn't necessarily supported by the stark performance difference between browsers.我几乎可以肯定这是我做错了,或者我编写的代码效率低下,但这并不一定受到浏览器之间明显的性能差异的支持。 Is chrome just that much better and handling react/constant rerenders? chrome 是否更好并处理反应/恒定重新渲染?

I know that this is a broad question, but I honestly don't understand what is happening here, or necessarily how to troubleshoot it beyond the developer tools.我知道这是一个广泛的问题,但老实说,我不明白这里发生了什么,或者必然如何在开发人员工具之外对其进行故障排除。 Any input or thoughts would be greatly appreciated.任何输入或想法将不胜感激。

The problem is your application is rendering too fast.问题是您的应用程序渲染速度太快。 In your particular case, there a few ways to improve that.在您的特定情况下,有几种方法可以改善它。

Every time you update the state, React needs to re-render your application, so updating the state within a loop is usually a bad idea.每次更新 state 时,React 都需要重新渲染您的应用程序,因此在循环中更新 state 通常是个坏主意。

Also, you are using useState 3 times, but only colors should be there, as App actually needs to re-render to reflect the changes there.此外,您正在使用useState 3 次,但应该只有colors应该在那里,因为App实际上需要重新渲染以反映那里的变化。 The other two pieces of state ( text and hex ) are only being used to pass data from the handleChange to the callback inside useEffect .另外两个 state( texthex )仅用于将数据从handleChange传递到useEffect内部的回调。

You can restructure your code to:您可以将代码重组为:

  • Avoid updating the state within a loop.避免在循环中更新 state。

  • Use a simple variable instead of state.使用简单变量代替 state。

  • Use useCallback to define a function with that logic that is not re-created on each render, as that forces TextInput to re-render as well.使用useCallback定义一个 function ,该逻辑不会在每次渲染时重新创建,因为这也会强制TextInput重新渲染。

  • Throttle this callback using something like this:使用以下方式限制此回调:

     import { useCallback, useEffect, useRef } from 'react'; export function useThrottledCallback<A extends any[]>( callback: (...args: A) => void, delay: number, deps?: readonly any[], ): (...args: A) => void { const timeoutRef = useRef<number>(); const callbackRef = useRef(callback); const lastCalledRef = useRef(0); // Remember the latest callback: // // Without this, if you change the callback, when setTimeout kicks in, it // will still call your old callback. // // If you add `callback` to useCallback's deps, it will also update, but it // might be called twice if the timeout had already been set. useEffect(() => { callbackRef.current = callback; }, [callback]); // Clear timeout if the components is unmounted or the delay changes: useEffect(() => window.clearTimeout(timeoutRef.current), [delay]); return useCallback((...args: A) => { // Clear previous timer: window.clearTimeout(timeoutRef.current); function invoke() { callbackRef.current(...args); lastCalledRef.current = Date.now(); } // Calculate elapsed time: const elapsed = Date.now() - lastCalledRef.current; if (elapsed >= delay) { // If already waited enough, call callback: invoke(); } else { // Otherwise, we need to wait a bit more: timeoutRef.current = window.setTimeout(invoke, delay - elapsed); } }, deps); }

If the reason to use useEffect is that you were not seeing the right values when updating colors , try using the version of setState that takes a callback rather then the new value, so instead of:如果使用useEffect的原因是您在更新colors时没有看到正确的值,请尝试使用接受回调而不是新值的setState版本,所以不要:

setColors([...colors, newColor]);

You would have:你将会拥有:

setColors(prevColors => ([...prevColors , newColor]));

The most common performance issues with react come from setting the state too many times since you're constantly re rendering the page and the elements within it. react 最常见的性能问题来自于设置 state 太多次,因为您不断地重新渲染页面和其中的元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM