React组件开发中常见的陷阱
React作为使用最广泛Web前端开发之一,在Web开发领域越来成熟和稳固。其新版本发布的Hook API/concept使得组件更加便捷易用。虽然如此,React开发中仍然有很多的陷阱值得每一位React拥趸关注。
陷阱一:使用函数式组件
在React中可以使用两种方法编组件函数式和类组件。函数式组件方式比较直观,所以被广为采用,但是函数式组件却存在问题:不支持Hook函数和没有内部state状态属性。
错误代码示例:
function Chongchong(props) { return <h1>Hello, {props.name}</h1>; }
问题分析:
函数式组件,不支持Hook函数,比如在组件加载后去请求API获取数据就不可能。
解决方案:
使用类组件,可以获得Hook和状态的加权。
陷阱二:错误的使用useState
在React中最重要的理念是对状态的处理,可以通过其控制整个数据流和状态渲染。当需要重新渲染树的时候,都是状态变化先行。
通过useState Hook,可以在功能组件中定义状态。这是处理状态简洁、方便的方法。因为如此,常常被滥用。
实例中,假设有两个按钮,一个按钮用来计数,另一个按钮用来发送计数或者或触发操作。但是,当前编号永远不会显示在组件内。仅当单击第二个按钮时才需要该请求。
错误代码示例:
问题分析:
在做出反应时,每个状态的变化都将迫使该组件及其子组件重新呈现。但是上面的代码中,由于未在渲染部分中使用该状态,因此每次设置计数器时,都会进行不必要的渲染,这会影响性能,还可能会产生副作用。
解决方案:
如果要在组件内部使用变量,变量值要在渲染前后保持,不强制重新渲染,则可以使用useRefHook。它会保留该值,不强制重新渲染组件。
陷阱三:用router.push代替链接
假设要编写一个按钮,然后单击该按钮,需要用户重定向到另一个页面。由于它是,因此此操作将是一种客户端路由机制。因此,将需要某种库来执行此操作。在react中,最常用的是react-router:
错误代码示例:
问题分析:
对于大多数用户来说这可以正常工作,但其可访问性仍然存在问题。按钮根本不会被标记为链接到另一个页面,这使得屏幕阅读器几乎无法识别按钮。可能无法在新标签页或窗口中打开。
解决方案:
在任何可能的情况下,跳转链接都应该用组件或常规的标签。
陷阱四:通过useEffect处理动作
React引入的最常用最好用Hook之一是"useEffect"Hook。该Hook允许处理与之相关prop或state发生变化的动作。很好用,但经常被误到可能不需要的地方。
一个组件场景:组件获取项目列表并将其呈现给dom。另外,如果请求成功,将调用"onSuccess"函数,该函数作为道具传递给组件。
错误代码示例:
问题分析:
上述代码使用了两个useEffect Hook,第一个Hook处理初始渲染时的API调用,第二个Hook调用onSuccess函数:假设没有加载,没有错误但状态为数据时,必须已成功调用。
这是正确的,并且可能永远不会失败。这样,也失去了动作和需要调用的功能之间的直接联系。无法保证这种情况只会在获取操作成功后才会发生。
解决方案:
最直接的方法是将"onSuccess"功能设置为在调用成功的实际位置:
现在一目了然,确切地表明了是在api调用成功的情况下onSuccess。
陷阱五:多个事件混用
什么时候该将一个组件拆分为几个较小的组件?如何构造组件树?在使用基于组件的框架时,每天都会出现所有这些问题。但是,设计组件时常见的错误是将两个用例组合到一个组件中。下面实例假设要显示标题为移动设备上的BurgerButton按钮或桌面屏幕上的标签。
错误代码示例:
问题分析:
通过这种方法,为HeaderInner组件设置两种状态。这会使得在其他地方测试或重用该组件变得更加困难。
解决方案:
分清楚事件,是要设置Header,Tabs或者BurgerButton,不要将两件事混用。
陷阱六:useEffectHook处理多个事件
例如,假设有一个组件以某种方式从后端获取一些数据,并且还根据当前位置显示Breadcrumbs。
错误代码示例:
问题分析:
有两个用例,即"数据获取"和"显示Breadcrumbs"。两者都用useEffectHook更新。更改useEffect时,将运行单个Hook。问题是,当位置更改时,也会调用该函数,这会带来副作用。
解决方案:
拆分效果,确保它们仅用于一种效果,这样的副作用也会消失。