很多react开发者在工作中会遇到一些看似简单却影响深远的问题。今天我们来聊聊五个常见的React错误,了解它们产生的原因和正确的做法。
当我们直接使用箭头函数创建被memo包裹的组件时,在React性能分析器中会显示为"Anonymous",这让我们很难识别是哪个组件在重复渲染。
import { memo } from 'react'
// 在性能分析器中显示为'Anonymous'
export const MyComponent = memo((props) => {
return <div>组件内容</div>
})
更好的做法是先声明组件,再用memo包裹:
const MyComponentInternal = (props) => {
return <div>组件内容</div>
}
// 在性能分析器中显示为'MyComponent'
export const MyComponent = memo(MyComponentInternal)
需要注意的是,不当使用memo反而会降低性能。因为每次渲染时比较props需要消耗资源,如果节省的渲染次数不足以抵消这个消耗,使用memo就没有意义。
在多个路由页面中使用相同的错误边界组件时,会出现一个问题:当用户从一个出错页面导航到另一个页面时,错误界面不会消失。
<Route path="books" element={
<ErrorBoundary>
<Books/>
</ErrorBoundary>
}/>
<Route path="users" element={
<ErrorBoundary>
<Users/>
</ErrorBoundary>
}/>
这是因为React认为这些错误边界是同一个组件,在导航时只是更新而不是重新挂载。
解决方法是为每个错误边界添加唯一的key:
<Route path="books" element={
<ErrorBoundary key="books">
<Books/>
</ErrorBoundary>
}/>
<Route path="users" element={
<ErrorBoundary key="users">
<Users/>
</ErrorBoundary>
}/>
或者创建自定义的错误边界组件:
const PageErrorBoundary = ({ children }) => {
const location = useLocation()
return <ErrorBoundary key={location.pathname}>{children}</ErrorBoundary>
}
JavaScript的.sort方法会直接修改原数组,这在React中可能引发问题。
const items = [3, 1, 2]
// 这会直接修改原数组
items.sort((a, b) => a - b)
console.log(items) // [1, 2, 3]
如果在state上使用.sort,其他依赖原数组顺序的组件就会出现问题。而且由于引用没有改变,使用setItems(items.sort())可能不会触发重新渲染。
正确的做法是创建新数组:
// 方法1:使用展开运算符
const sortedItems = [...items].sort((a, b) => a - b)
// 方法2:使用toSorted(较新浏览器)
const sortedItems = items.toSorted((a, b) => a - b)
// 方法3:在map或filter之后使用sort是可以的
const processedItems = items
.filter(item => item.active)
.sort((a, b) => a.name.localeCompare(b.name))
在JavaScript中,我们经常用数组长度作为条件判断:
// 当items.length为0时,会显示数字0
items.length && <List items={items} />
这是因为React会渲染数字0,导致界面上出现一个多余的"0"。
应该使用明确的比较:
// 正确做法1
items.length > 0 && <List items={items} />
// 正确做法2
!!items.length && <List items={items} />
// 正确做法3
items.length ? <List items={items} /> : null
useEffect和useLayoutEffect的执行时机不同:
useEffect:在dom更新后异步执行,用户可能看到中间状态
useLayoutEffect:在DOM更新后同步执行,确保用户看到最终状态
// 可能导致闪烁
useEffect(() => {
// 副作用代码
}, [dependency])
// 避免闪烁
useLayoutEffect(() => {
// 需要同步执行的副作用
}, [dependency])
使用建议:
涉及DOM测量和同步更新的操作使用useLayoutEffect
数据获取、事件监听等异步操作使用useEffect
服务端渲染时注意useLayoutEffect会警告,需要特殊处理
在处理列表时,很多开发者会使用索引作为key,这可能导致问题:
// 不推荐
{items.map((item, index) => (
<div key={index}>{item.name}</div>
))}
// 推荐使用唯一ID
{items.map(item => (
<div key={item.id}>{item.name}</div>
))}
当列表可能重新排序时,使用索引作为key会导致组件状态混乱。
这些React开发中的常见错误看似简单,但对应用性能和用户体验影响很大。通过理解这些问题的根源并采用正确的解决方案,我们可以写出更健壮、更高效的React代码。
记住,好的React开发不仅仅是让代码工作,还要考虑性能、可维护性和用户体验。希望这些建议能帮助你在React开发中避免这些陷阱。
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!
vue工程npm run serve/start/dev启动时,node_modules文件报:Cannot read property range of null 错误,该问题是babel-eslint版本更新问题导致的;
在ajax请求后台数据时有时会报 HTTP 400 错误 - 请求无效 (Bad request);出现这个请求无效报错说明请求没有进入到后台服务里;原因:前端提交数据的字段名称或者是字段类型和后台的实体类不一致
我们都知道 try catch 无法捕获 setTimeout 异步任务中的错误,那其中的原因是什么。以及异步代码在 js 中是特别常见的,我们该怎么做才比较?
父页面初始化声明变量a为数组(数组对象是引用类型,赋值传递的是地址),创建iframe子页面后给父页面变量a赋值,赋值后销毁iframe子页面,再次调用变量a的时候就会抛出异常‘SCRIPT5011:不能执行已释放Script的代码’。
js错误的实质,也是发出一个事件,处理他,error实例对象message:错误提示信息,name:错误名称(非标准属性)宿主环境赋予
文件上传的功能时候,调用fs.renameSync方法错误,这个提示是跨区重命名文件出现的权限问题。先从源文件拷贝到另外分区的目标文件,然后再unlink,就可以了。
如果在JavaScript中使用innerHTML,缺点是:内容随处可见;不能像“追加到innerHTML”一样使用;innerHTML不提供验证,因此我们可能会在文档中插入有效的和破坏性的HTML并将其中断
现在,有越来越多所谓的“教程”来帮助我们提高网站的易用性。我们收集了一些在Web开发中容易出错和被忽略的小问题,并且提供了参考的解决方案,以便于帮助Web开发者更好的完善网站。
为什么要做前端错误监控?1. 为了保证产品的质量2. 有些问题只存在于线上特定的环境3. 后端错误有监控,前端错误没有监控,前端错误分为两类: 即时运行错误和资源加载错误
当我们在进行开发的时候,通常需要属于我们自己的错误类来反映任务中可能出现的特殊情况。对于网络操作错误,我们需要 HttpError,对于数据库操作错误,我们需要 DbError,对于搜索操作错误,我们需要 NotFoundError,等等
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!