我正在尝试使用React 16.8.3构建一个Navbar。我想使用组合来传递Navbar内容,而不是通过prop来传递配置对象,以便具有更大的灵活性。像这样:
<Navbar>
<NavItem>Some label</NavItem>
<NavItem>
<span>Some arbitrary content</span>
<NavItem>
</Navbar>
代替:
const navItems = [
{
label: 'Some label'
},
{
label: 'Some other label'
}
]
<Navbar items={navItems} />
到目前为止,导航栏工作正常。我在shouldComponentUpdate方法中添加了一些逻辑,以防止多次重新渲染:
shouldComponentUpdate(nextProps) {
return nextProps.selectedItem !== this.props.selectedItem;
}
因此,Navbar仅在其选定项更改时才重新渲染,而不是在Navbar父项重新渲染时不重新渲染。
问题是,一个NavItem包含一个带有任务计数的徽章,每当用户执行某些任务时,该徽章必须更新:
,项目标记为:
<Navbar>
<NavItem>
<div className="has-badge">
<span>Label</span>
<span className="badge">{this.props.toDoCount}</span>
</div>
</NavItem>
</Navbar>
this.props.toDoCount 是Navbar父项的道具,而不是Navbar本身的道具。
如何在不重新呈现整个导航栏的情况下更新徽章编号 ?到目前为止,我已经尝试创建一个Badge组件,添加一些状态以及使用Navbar父级中的ref更新徽章编号的方法:
import React, { PureComponent } from 'react';
interface BadgeProps {
number: number;
}
class Badge extends PureComponent<BadgeProps> {
state = {
number: 0
};
setCount(number) {
this.setState({
number
});
}
render() {
return <span className="badge">{this.state.number}</span>;
}
}
在导航栏父项中:
private todos = createRef<Badge>();
...
componentDidUpdate(prevProps: EhrProps) {
this.todos.current.setCount(toDosCount);
}
它正在工作,但是...在React中有没有更简单或更干净的方法?
谢谢!
PS:我们在项目中使用Redux,但我想避免在Navbar或其项目中使用商店。
编辑:
我在Navbar的render方法中使用React.children和React.cloneElement:
render() {
const { className, children, selectedItem, ...rest } = this.props;
const classes = classNames(
{
navbar: true
},
className
);
return (
<nav className={classes} {...rest}>
{React.Children.map(children, child => {
if (child.type === NavItem) {
return React.cloneElement(child, {
onClick: this.handleItemClick,
selected: child.props.name === selectedItem
});
}
return child;
})}
</nav>
);
}
每个NavItem都会处理自己的渲染:
return (
<div className={classes} onClick={handleClick} onKeyPress={handleKeyPress} role="menuitem" tabIndex={0}>
{children}
</div>
);
答案 0 :(得分:0)
大概是Navbar
组件的一些代码看起来像这样。
class Navbar extends React.Component<Props> {
render() {
return (
<div>
{this.props.navItem.map(item => <NavItem key={item.label}>{item.label}</NavItem>)};
</div>
);
}
}
,然后提供一些代码来渲染每个孩子NavItem
。
要使组件相当有效,只需重新渲染整个Navbar就足够了,而不必重新渲染每个孩子。
我推荐的是:
NavItem
componentShouldUpdate
或React.PureComponent
(研究一下!一旦理解,这是一个很好的通用解决方案,默认情况下对每个组件使用React.Component代替),以确保每个子组件仅在其值更改时重新渲染当您更新单个NavItem的标志时,将发生Navbar
重新渲染的情况。大多数NavItems
会看到其道具没有更改,也没有重新呈现。拥有徽章的Navbar
的单个孩子将被更改,并将重新呈现。这样,实际的开销实际上很低。
如果您的Navbar
拥有大量孩子,或者该单身孩子的徽章发生了很大变化,则您可以使用React.Context
或Redux传递该单身孩子的价值来进一步优化,但感觉很混乱,似乎过早了优化。
祝你好运!