1. 避免内联定义React.memo
假如在memo包裹内直接采用箭头函数来定义组件,那么在React性能剖析工具中,这个组件将缺少明确的名称显示。
import { memo } from 'react' // 这会在剖析器中显示为'Anonymous' export const MyComponent = memo((props) => /* ... */)取而代之的是,它会显现为“Anonymous”(匿名),这让我们难以辨识哪个组件导致了多余的渲染操作。
这种情况颇为不便,因为应用memo的目的往往是为了通过Profiler验证记忆化机制是否有效运转。
要规避此问题,可将组件独立定义到一个变量里:
const MyComponentInternal = (props) => /* ... */ // 这会在剖析器中显示为'MyComponent' export const MyComponent = memo(MyComponentInternal)另外值得一提,若记忆化未被恰当运用,反而可能导致应用性能下降。每次渲染时比较props都需要开销,如果这些开销无法被省略的渲染所弥补,那么引入memo只会使程序运行更迟缓。
别在所有路由中重复同一错误边界
假设你的应用包含多个页面,且每个页面都包裹了相同的错误边界组件,那么用户切换到其他页面时,错误界面不会自动清除。
// 导航到另一页面时,错误画面仍会保留 <Route path="books" element={<ErrorBoundary><Books /></ErrorBoundary>} /> <Route path="users" element={<ErrorBoundary><Users /></ErrorBoundary>} /> <Route path="settings" element={<ErrorBoundary><Settings /></ErrorBoundary>} />原因在于React视这些错误边界为同一实例,因此导航视为组件更新,其内部错误状态得以保持。
可以通过添加key属性来区分它们,从而解决问题:
<Route path="books" element={<ErrorBoundary key="books"><Books /></ErrorBoundary>} /> <Route path="users" element={<ErrorBoundary key="users"><Users /></ErrorBoundary>} /> <Route path="settings" element={<ErrorBoundary key="settings"><Settings /></ErrorBoundary>} />或者,设计一个自定义错误边界组件,根据URL路径的基础名称设置内部key:
const PageErrorBoundary = ({ children }) => { const match = useMatch('*') return <ErrorBoundary key={match.pathBasename}>{children}</ErrorBoundary> }规避sort方法的变异特性
sort函数会直接修改原数组。正如其他变异操作一样,这在React环境中容易引发多种缺陷。
始终优先采用不可变更新方式。
const items = [3, 1, 2] // 这会更改原始数组 items.sort((a, b) => a - b) console.log(items) // [1, 2, 3]若在状态数组上调用sort,而另一组件依赖其原始未排序序列,就可能导致意外错误。
此外,如果在状态设置中这样操作:setItems(items.sort()),它不会触发更新,因为数组引用未变。
作为替代,可利用不可变的toSorted方法,不过它在较旧浏览器中不可用。若需兼容旧版,可借助扩展运算符实现。
return ( // 运用扩展运算符防止变异 [...items].sort((i1, i2) => i1.name.localeCompare(i2.name)) )需注意,如果在sort前先执行filter或map,这些方法会生成新数组,因此安全。只有直接对状态调用sort时才会出问题。
避免直接以0作为条件判断
例如,在JavaScript中,你可能习惯编写这样的代码:
{items.length && <List items={items} />}React会将数字渲染到界面上,因此如果列表长度为0,UI会显示一个'0'字符,而非预期地跳过渲染列表。
可改为使用items.length > 0作为条件来防止此情况。
{items.length && <List items={items} />} // 这会显示0 {items.length > 0 && <List items={items} />} // 这正常当然,也可采用双重否定运算符,如:
{!!items.length && <List items={items} />}优先选择useLayoutEffect而非useEffect
useEffect并非在每次渲染后立即运行,而是等到DOM变更完成后稍作延迟才执行。这可能导致用户短暂瞥见应用处于中间状态的界面。
这种延迟会引发不雅观的闪烁效果。
相反,useLayoutEffect会在DOM更新后同步触发,从而确保在屏幕重绘前,用户始终看到最终一致的状态。
因此,useLayoutEffect能有效消除闪烁。但对于非UI相关的副作用,如网络调用或事件监听器同步,使用useEffect已然足够。
最后
送人玫瑰,手留余香,觉得有收获的朋友可以点赞,关注一波 ,我们组建了高级前端交流群,如果您热爱技术,想一起讨论技术,交流进步,不管是面试题,工作中的问题,难点热点都可以在交流群交流,为了拿到大Offer,邀请您进群,入群就送前端精选100本电子书以及 阿里面试前端精选资料 添加 下方小助手二维码或者扫描二维码 就可以进群。让我们一起学习进步.
862

被折叠的 条评论
为什么被折叠?



