我是一个快节奏的人:我很快就吃饭,快速走路,然后迅速做出决定。不过,我无法忍受的是一个缓慢的应用程序 - 尤其是我正在从事的应用程序。因此,我总是发现自己不得不仔细检查其性能:检查它重新渲染的次数,DOM的大小以及用户交互的速度等。在使用这些数据的情况下,我通过以目标方式来完善代码库来逐步提高应用程序的性能。
现在,我想分享一些可以帮助提高应用程序性能的策略:
-
请注意您在每个组件中使用的钩子:从我的角度来看,这至关重要。
useState
和useEffect
是最常用的钩子,但有时可以通过重构来消除它们,而无需牺牲功能。更少的挂钩意味着更少的重新租用器,这又意味着更快的应用程序。其他值得注意的挂钩是useCallback
和useMemo
,它们会记住值,并将其存储在内存中。在更大范围内,这可能会对性能产生影响。React.memo()
也是如此。
简单示例:
想象您有一个组件可以跟踪用户的名字,姓氏和年龄。一种天真的方法可能是声明三个单独的useState
钩子:
const UserProfile = () => {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [age, setAge] = useState(0);
// Multiple function calls to update the user profile
const updateUserProfile = () => {
setFirstName('John');
setLastName('Doe');
setAge(30);
};
return (
<div>
<h1>{`${firstName} ${lastName}`}</h1>
<p>Age: {age}</p>
<button onClick={updateUserProfile}>Update Profile</button>
</div>
);
};
每次调用这些钩子时,该组件都会同时重新渲染。我们可以使用一个对象将其凝结到一个单个useState
中:
const UserProfile = () => {
const [user, setUser] = useState({
firstName: '',
lastName: '',
age: 0,
});
// Single function call to update the user profile
const updateUserProfile = () => {
setUser({
firstName: 'John',
lastName: 'Doe',
age: 30,
});
};
return (
<div>
<h1>{`${user.firstName} ${user.lastName}`}</h1>
<p>Age: {user.age}</p>
<button onClick={updateUserProfile}>Update Profile</button>
</div>
);
};
现在,我们只有一个钩子,只有一个钩子被调用时只有一个钩子。宾果游戏。
- 最小化DOM节点的数量:我总是问自己:“可以安全地删除此HTML标签吗?”如果答案是肯定的,我将其删除。较少的节点会带来更好的性能。
简单示例:
如果仅用于造型目的而使用空的div
找到代码,请考虑使用CSS网格或Flexbox实现相同的布局,从而减少DOM节点的数量。
// Before
<div className="wrapper">
<div className="innerWrapper">
<Component />
</div>
</div>
// After
<div className="optimizedWrapper">
<Component />
</div>
- 偏爱基于班级的样式而不是内联样式:内联样式被认为是每个渲染上的新对象,这可以使React认为某些事情发生了变化,从而触发了不必要的重新呈现并影响性能。还值得注意的是,在单独的文件中维护样式有助于保持样式一致。
简单示例:
// Before
<div style={{ display: 'flex' }}>
// After
<div className='container'>
// In a separate css file:
.container: {
display: flex
}
-
更喜欢从材料UI或类似UI库中的简单
div
而不是Box
:本机HTML元素通常提供更好的性能,因为它们不带有其他React组件的开销,包括生命周期方法和上下文消耗。
简单示例:
// Before
<Box p={2}>
// After
<div className="container">
// In a separate css file:
.container: {
padding: '2px'
}
-
更喜欢从材料UI或类似的UI库中的有条件类别的
makeStyles
中的条件类别:使用基于条件切换的预定义类可以更具性能,因为它不会在运行时生成新类。
简单示例:
// Before
const useStyles = makeStyles({
root: {
backgroundColor: props => props.isActive ? 'blue' : 'white',
},
});
// After
const className = isActive ? 'active' : 'inactive';
- 选择功能组件:有几个令人信服的原因。首先,对于WebPack(例如WebPack)的构建工具而言,功能组件更容易通过“树木摇动”来优化,该工具仅包括最终捆绑包中实际使用的代码。其次,功能组件通常会导致较小的组件树和更少的生命周期方法,从而使React的扩散算法可以更快地更新到DOM。最后,功能组件比类组件使用的内存少,这在内存有限的环境中特别有益。
简单示例:
// Before
class MyComponent extends React.Component {
state = { /* ... */ };
componentDidMount() { /* ... */ }
render() { /* ... */ }
}
// After
const MyComponent = () => {
const [state, setState] = useState(/* ... */);
useEffect(() => { /* ... */ }, []);
return (/* ... */);
};
通过尝试这些技巧并使它们成为编码例程的常规一部分,您不仅仅是通往更快的React应用程序的道路,而且您还将使您的用户更加顺畅。
让我们一起创建更好的应用=)。