相关文章
react项目优化
使用 React.memo() 缓存组件
对于函数式组件,可以使用 React.memo() 缓存组件,以减少不必要的重新渲染。这样可以避免在 props 没有变化时触发组件的重新渲染。
1 2 3 4 5 6 7 8 9 10 11 12
| import React from 'react';
const ChildComponent = React.memo(({ name }) => { console.log('Rendering ChildComponent'); return ( <div> Hello, {name}! </div> ); });
export default ChildComponent;
|
在这个例子中,当父组件重新渲染时,如果传递给 ChildComponent 的 name props 没有发生变化,那么子组件将不会重新渲染。这样可以减少不必要的渲染,提高应用程序的性能。
使用 React.lazy() 实现组件懒加载
使用 React.lazy() 和 Suspense 组件来实现组件的按需加载,减少初始加载时的资源请求,提高页面加载速度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import React, { Suspense } from 'react';
const Home = React.lazy(() => import('./Home')); const About = React.lazy(() => import('./About'));
const App = () => { return ( <div> <h1>My App</h1> <Suspense fallback={<div>Loading...</div>}> <Home /> <About /> </Suspense> </div> ); };
export default App;
|
在这个案例中,我们将 Home 和 About 组件使用 React.lazy() 异步加载,然后在 App 组件中使用 Suspense 组件来包裹这两个懒加载组件。当这两个组件加载完成之前,Suspense 组件会显示一个 loading 提示。这样可以在需要时按需加载组件,提高应用程序的性能和加载速度。
避免不必要的状态更新
在使用 setState 更新状态时,应该放在事件处理函数中,避免在 render 方法中执行 setState,以免触发不必要的重新渲染。
错误写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import React, { useState } from 'react';
const Counter = () => { const [count, setCount] = useState(0);
setCount(prevCount => prevCount + 1);
console.log('Rendering Counter');
return ( <div> <h2>Counter: {count}</h2> </div> ); };
export default Counter;
|
正确写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import React, { useState, useEffect } from 'react';
const Counter = () => { const [count, setCount] = useState(0);
useEffect(() => { setCount(prevCount => prevCount + 1); });
console.log('Rendering Counter');
return ( <div> <h2>Counter: {count}</h2> </div> ); }; export default Counter;
|
使用高阶组件(HOC)优化逻辑
使用高阶组件将通用逻辑提取出来,避免在多个组件中重复编写相同的逻辑代码,提高代码复用性和可维护性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import React, { useEffect } from 'react';
const withLogger = WrappedComponent => { return props => { useEffect(() => { console.log(`Component ${WrappedComponent.name} mounted`); return () => { console.log(`Component ${WrappedComponent.name} unmounted`); }; }, []);
return <WrappedComponent {...props} />; }; };
const MyComponent = ({ name }) => { return <div>Hello, {name}!</div>; };
const EnhancedComponent = withLogger(MyComponent);
export default EnhancedComponent;
|
优化列表渲染
对于长列表或大量数据的渲染,可以使用虚拟滚动技术(如 react-virtualized)来优化渲染性能,只渲染可见区域的内容,减少内存占用和渲染开销。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import React from 'react'; import { List } from 'react-virtualized'; import 'react-virtualized/styles.css';
const generateListData = (count) => { const data = []; for (let i = 0; i < count; i++) { data.push(`Item ${i}`); } return data; };
const VirtualizedListExample = () => { const listData = generateListData(1000);
const rowRenderer = ({ index, key, style }) => { return ( <div key={key} style={style}> {listData[index]} </div> ); };
return ( <div style={{ height: 300, width: '100%' }}> <List rowCount={listData.length} // 列表项数量 rowHeight={30} // 列表项高度 width={300} // 列表宽度 height={300} // 列表高度 rowRenderer={rowRenderer} // 列表项渲染函数 /> </div> ); };
export default VirtualizedListExample;
|
使用 React Fragments 避免额外标记
React Fragments(或称为片段)是一种用来包裹多个子元素而不会在 DOM 中增加额外节点的技术。
1 2 3 4 5 6 7 8 9 10 11 12
| import React from 'react';
const MyComponent = () => { return ( <> <h1>Hello</h1> <p>World</p> </> ); };
export default MyComponent;
|
在这个示例中,<>…</> 就是一个 React Fragment,它包裹了两个子元素 h1 和 p。在 DOM 结构中,这两个元素不会增加额外的节点,而是直接作为父元素的子节点。
不要使用内联函数定义
在 React 中,内联函数定义指的是将函数作为 JSX 元素的属性值直接传递
错误写法
1 2 3 4 5
| function MyComponent() { return ( <button onClick={() => console.log('Clicked')}>Click me</button> ); }
|
正确写法
1 2 3 4 5 6 7 8 9 10
| function handleClick() { console.log('Clicked'); }
function MyComponent() { return ( <button onClick={handleClick}>Click me</button> ); }
|