全文共1955字,预计学习时长10分钟
图源:unsplash
俗话说,熟能生巧,大多数时候笔者都在使用React工作。时间久了,一些小技巧也不请自来,它们着实让人获得了意外之喜。
并不是每个人都发现了这些技巧,笔者的很多同事就还没有发现。但它们确实简单好用,让人心情愉悦。一起来看看吧!
以下所有例子均围绕功能性组件(components)和钩子(hooks)展开。
React 带键的片段
有时,需要在列表内渲染多种组件。如果不需要容器,就可以使用React 片段。示例如下:
-
const pokemons = [
'Charizard',
'Mr. Mime',
'Jynx']
-
pokemons.map(
pokemon => (
-
<>
-
<strong>Name:
</strong>
-
<span>{pokemon}
</span>
-
</>
-
))
上述代码没有问题,但React会对键进行提示:
Warning: Each child in a listshould have a unique "key" prop.
程序猿一般会认为这没什么大不了,用div替换片段就好啦。
这么做当然没有问题,但如果改可以使用带键的React片段,即使用 <React.Fragment>改变语法,这样一切都迎刃而解:
-
pokemons.map(
pokemon => (
-
<React.Fragmentkey={pokemon}>
-
<strong>Name:
</strong>
-
<span>{pokemon}
</span>
-
</React.Fragment>
-
))
向setState传递函数
useState和useEffect恐怕是最常使用的钩子了。程序员需要向useEffect传递依赖项,否则就会出错或会出现意外结果。然而,如果依赖项仅仅是和相关 setState连用的状态,或许就无需对其进行传递了。
先来看个不太完美的版本:
-
const [count, setCount] =useState(
0)
-
useEffect(
() => {
-
const id =setInterval(
() => {
-
setCount(count +
1);
-
},
1000);
-
return
() =>clearInterval(id);
-
}, [count]);
更新之后是什么样呢:
-
const [count, setCount] =useState(
0)
-
useEffect(
() => {
-
const id =setInterval(
() => {
-
setCount(
c => c +
1);
-
},
1000);
-
return
() =>clearInterval(id);
-
}, []);
用useReducer实现useState
这是笔者在推特上发现的,尽管没有实际作用,但可以了解 useReducer的能力。
如果直接从useReducer进行返回操作,那么它将和useState起到几乎同样的作用。有人可能会说使用useState没有必要。那篇推文是这样讲的:
代码如下,可自行拷贝尝试:
const [name, setName] =useReducer((_, value) => value, 'James');<input value={name} onChange={e =>setName(e.target.value)} />
将字符串值作为HTML元素
有时,程序员希望创建一个能够成为灵活HTML元素的组件。或许读者见过来自CSS-in-JS库的as prop,比如emotion。
假设要创建一个能够渲染为button或 a 的<Button> 组件,有哪些选择呢?可以用它提取样式,创建两个不同的组件;也可以只创建一个组件,一起使用 React.createElement 和 as prop:
-
constButton= ({
as =
'button', ...props }) => React.createElement(
as, props)
-
<Button>A Button</Button>
// Renders a button element
-
<Buttonas=
"a">A Link</Button>
// Renders an anchor element
对于简单的组件来说,这已经很不错了,但有没有更好的方法呢?看看这个::
-
constButton=
({ Component ='button', ...props }) => <Component {...props} />
-
<Button>A Button</Button>
// Renders a button element
-
<ButtonComponent=
"a">A Link<
/Button> /
/ Renders an anchor element
没错,可以在JSX中把字符串作为组件——保证字符串组件的名称以大写字母打头即可。
手动对组件进行重新渲染
你一定有过需要手动对组件进行重新渲染的经历吧?比如,需要重新渲染组件的时候,手头没有任何状态或可用的物件。
假设处于某些特殊原因,需要在点击按钮时进行此项操作,可以这么做:
const [, rerender] =useState()rerender({})
代码中用到了useState,但不需要状态本身。需要的只是 setState函数或rerender 函数,以达到重新渲染的目的。Bingo!
需要注意的是,每次运行时,都需要传递一个新的值,比如一个空白对象或数组。
图源:unsplash
若无直接可用的prop或状态依赖项,可将对象或函数从组件中移除
这是很常见的错误,首来看代码:
-
constPokemon=
({ type, name }) => {
-
const cardProps = {
-
fire: {
primaryColor:
'red',
secondaryColor:
'yellow' },
-
ice: {
primaryColor:
'blue',
secondaryColor:
'white' }
-
}
-
return
<Card {...cardProps[type]}>Name: {name}</Card>
-
}
想法不错——比使用if/else或 switch语法好多了。但还是有问题。该组件每次都会重新渲染一个新创建的cardProps对象。即使没有任何改变,对所有依赖组件的重新渲染还是会发生。
使用useMemo 能够解决这一问题:
-
constPokemon=
({ type, name }) => {
-
const cardProps =useMemo(
() => ({
-
fire: {
primaryColor:
'red',
secondaryColor:
'yellow' },
-
ice: {
primaryColor:
'blue',
secondaryColor:
'white' }
-
}), [])
-
return
<Card {...cardProps[type]}>Name: {name}</Card>
-
}
但这样做要付出代价。仔细观察代码就不难发现,把cardProps对象放到组件里没有必要。所以把 useMemo 放上去也没必要,因为对象在props或状态上没有直接的依赖项。即使来自外部,还是可以使用...cardProps[types]。
-
const cardProps = {
-
fire: {
primaryColor:
'red',
secondaryColor:
'yellow' },
-
ice: {
primaryColor:
'blue',
secondaryColor:
'white' }
-
}
-
constPokemon=
({ type, name }) => <Card{...cardProps[type]}>Name: {name}<
/Card>
看到了吧,无需任何钩子。如果不需要,就移除它们——函数也是同理。
学无止境,值得探索的东西还很多,这些技巧你学会了嘛~
留言 点赞 关注
我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”
(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)
转载:https://blog.csdn.net/duxinshuxiaobian/article/details/105366534