简体   繁体   English

优化 React 应用程序 - 仅针对 React [React.JS]

[英]Optimizing React Application - in terms of React Only [React.JS]

I got an interview today, where Interviewer asked me how will you improve performance of your "React Application" - in terms of react only.我今天接受了面试,面试官问我你将如何提高“反应应用程序”的性能 - 仅就反应而言。

He did not want any answer in terms of CSS (concatenation/minifying), JS (concatenation/minifying), Images (Image-Sprites or Using SVGs).他不想要任何关于 CSS(串联/缩小)、JS(串联/缩小)、图像(Image-Sprites 或 Using SVGs)的答案。

Now, what hint I could get was using:现在,我能得到的提示是使用:

  • React-Memo反应备忘录
  • useCallback hook使用回调钩子

Now, I have actually no clue what he was talking about?现在,我真的不知道他在说什么? Can someone help me out understanding how these 2 help optimzing in terms of React?有人可以帮助我了解这两个如何帮助优化 React 吗? Also, is there any other way (specifically, related in terms of React only of how to optimize performance of React-Apps)?另外,有没有其他方法(具体来说,仅与 React 相关的如何优化 React-Apps 的性能)?

Any help would be appreciated!任何帮助,将不胜感激!

This article might help you: A (Mostly) Complete Guide to React Rendering Behavior这篇文章可能对你帮助: A (Mostly) Complete Guide to React Rendering Behavior

From that article you will see that React will compare the before and after virtual DOM tree and look for differences.从这篇文章,你会看到,会做出反应比较beforeafter的虚拟DOM树,寻找差异。 Whenever it finds one, it will schedule for re-render that whole tree which is under that tree node.每当它找到一个时,它就会安排重新渲染该树节点下的整棵树。 Ie: A parent re-renders, all of its children will re-render too.即:父级重新渲染,其所有子级也将重新渲染。 Unless you tell React to re-use some stuff it has rendered previously and that has not changed.除非你告诉 React 重用一些它之前渲染过的东西,而且没有改变。

React.memo API reference React.memo API 参考

The way you can optimize your React app with React.memo() and React.useCallback looks something like this:使用React.memo()React.useCallback优化 React 应用程序的方式如下所示:

1 - An unoptimized React app: 1 - 未优化的 React 应用程序:

See that when you click the button, App re-renders.看到当您单击按钮时, App重新呈现。

Even though nothing new is being passed to both child components, they also re-render.即使没有新的东西被传递给两个子组件,它们也会重新渲染。 That's React's default behavior.这是 React 的默认行为。

 function App() { console.log("Rendering App..."); const [boolean,setBoolean] = React.useState(false); const someFunction = () => { console.log("Running someFunction..."); } return( <React.Fragment> <Component1/> <Component2 someFunction={someFunction} /> <button onClick={() => setBoolean((prevState) => !prevState)}> Re-render App </button> </React.Fragment> ); } const Component1 = (props) => { console.log("Rendering Component1..."); return( <div>I am component 1</div> ); }; const Component2 = (props) => { console.log("Rendering Component2..."); return( <div>I am component 2</div> ); } ReactDOM.render(<App/>, document.getElementById("root"));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script> <div id="root"/>

2 - React App optimized with React.memo() 2 - 使用React.memo()优化的 React App

React.memo() tells React something like that: if the new render will call that memoized component with the exact same props from the last render, don't render it again. React.memo()告诉 React 类似的东西:如果新渲染将使用与上次渲染完全相同的props调用该记忆化组件,则不要再次渲染它。 'Cause same props will produce same result anyway.因为无论如何相同的props都会产生相同的结果。

You will see that Component1 has stopped re-rendering, since it keeps being called with empty props .您将看到Component1已停止重新渲染,因为它一直被空props调用。 But Component2 keeps re-rendering.但是Component2一直在重新渲染。 That's because every time you re-render App , a new someFunction variable with a new reference for the function is being created, thus, is also being changed.那是因为每次重新渲染App ,都会创建一个新的someFunction变量,该变量具有该函数的新引用,因此也会被更改。

And React only does a shallow compare .而 React 只做一个浅层比较 It does not look into the someFunction code.它不会查看someFunction代码。 It only compares the reference for that variable (or a value, in case of a primitive ).它只比较该变量的引用(或值,如果是原始)。 If any of the props is different than last render, it will re-render.如果任何props与上次渲染不同,它将重新渲染。

 function App() { console.log("Rendering App..."); const [boolean,setBoolean] = React.useState(false); const someFunction = () => { console.log("Running someFunction..."); } return( <React.Fragment> <Component1/> <Component2 someFunction={someFunction} /> <button onClick={() => setBoolean((prevState) => !prevState)}> Re-render App </button> </React.Fragment> ); } const Component1 = React.memo((props) => { console.log("Rendering Component1..."); return( <div>I am component 1</div> ); }); const Component2 = React.memo((props) => { console.log("Rendering Component2..."); return( <div>I am component 2</div> ); }); ReactDOM.render(<App/>, document.getElementById("root"));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script> <div id="root"/>

3 - Optimized with React.memo() and React.useCallback() 3 - 使用React.memo()React.useCallback()

You'll see now that only App re-renders.您现在会看到只有App重新渲染。 Because useCallback "tells" React to keep the function reference from the very first render and only change it if necessary.因为useCallback “告诉” React 在第一次渲染时保留函数引用,并且仅在必要时更改它。 In this example, it will never change, because we've passed an empty array for useCallback .在这个例子中,它永远不会改变,因为我们已经为useCallback传递了一个空数组。

Since it won't change, Component2 will no longer be re-rendered every time, 'cause it will receive always the same props .由于它不会改变,因此Component2将不再每次都重新渲染,因为它将始终接收相同的props

useCallback API reference useCallback API 参考

 function App() { console.log("Rendering App..."); const [boolean,setBoolean] = React.useState(false); const someFunction = React.useCallback(() => { console.log("Running someFunction..."); },[]); return( <React.Fragment> <Component1/> <Component2 someFunction={someFunction} /> <button onClick={() => setBoolean((prevState) => !prevState)}> Re-render App </button> </React.Fragment> ); } const Component1 = React.memo((props) => { console.log("Rendering Component1..."); return( <div>I am component 1</div> ); }); const Component2 = React.memo((props) => { console.log("Rendering Component2..."); return( <div>I am component 2</div> ); }); ReactDOM.render(<App/>, document.getElementById("root"));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script> <div id="root"/>

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

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