您是否赋予了 React.Fragment 正确的意义?
更新:由于对标题及其内容的误解,标题已更改。我希望此更改能够满足预期,并保持健康的对话,最终让我们作为开发人员、程序员和专业人士不断成长。
在我超过 15 年的编码、编程和架构经验中,我发现有些人编写的代码没有规则或标准,有时甚至有人自以为遵循了一些规则,但实际上他们自己并没有真正遵守。我经常遇到这种情况,有时也会继续遇到。我写这篇文章是为了分享我认为的良好实践,并以此帮助我们成为优秀的专业人士。
问题
如果传递的数组包含项目,则以下React代码会呈现项目列表。
function List(props) {
const items = props.items;
return <ul>
{items && items.map(i => <li key={i}>{i}</li>)}
</ul>;
}
function App() {
const collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
return <List items={collection} />;
}
ReactDOM.render(App(), document.getElementById('app'));
你觉得这段代码有什么问题吗?这段代码运行正常,它创建了一个li
以数字为值的节点。
如果数组中没有任何元素,会发生什么?ul
节点也会被渲染,但其中既没有任何li
节点,也没有任何元素。这不是什么大问题,但确实存在一些问题。
我们可以这样修改代码:
function List(props) {
const items = props.items;
// *** notice how the code is modified and complex increases
return items &&
<ul>
{ items.map(i => <li key={i}>{i}</li>) }
</ul>;
}
function App() {
const collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
return <List items={collection} />;
}
ReactDOM.render(App(), document.getElementById('app'));
与前一种情况一样,此代码运行良好,它完成了它应该做的事情。
那么,让我问与之前相同的问题,如果数组中没有项目会发生什么?
在这种情况下,false
返回一个值,而不是 HTML 节点。这里的问题是,我们根据传递的属性返回不同类型的项目items
。
为什么这是个问题?实际上,这不仅仅是一个编码问题,而是一个概念问题。在这个函数中返回相同类型的项将使其更易于测试、维护和阅读,因为它将保持一致,并且调用此函数的其他方法将收到它们所期望的内容,而无需检查是否检索了布尔值或组件。
下一步的代码修改必须考虑到这个前提,因此它将如下所示:
function List(props) {
const items = props.items;
// check if items is not empty
const isEmpty = !(items && items.length > 0);
// always return a React component
return isEmpty
? <React.Fragment />
: (<ul>
{ items.map(i => <li key={i}>{i}</li>) }
</ul>);
}
function App() {
const collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
return <List items={collection} />;
}
ReactDOM.render(App(), document.getElementById('app'));
现在我们的代码看起来更合理了,不是吗?我们总是为代码采用的任何选项或路径返回一个组件。如果 items 不为空,ul
则返回一个节点,并且li
每个节点都包含一个节点,实际上是一个 React 组件。
如果没有条目,React.Fragment
则返回一个组件。它们都是React 组件,调用者无需检查。
作为一名专业的程序员,我们必须赋予我们的对象意义和名称。
你可能注意到了,我们的代码中有几个对象:一个空列表组件、一个项目列表组件、一个项目组件和一个管理器组件。每个组件都有其独特的职责(遵循我将在后续文章中讨论的单一职责原则),并且代码简洁,易于理解、维护和测试。
function ListItem(props) {
return <li>{props.value}</li>;
}
function ItemList(props) {
const items = props.items;
return <ul>
{ items.map(i => <ListItem key={i} value={i} />) }
</ul>;
}
// As suggested by Andy Nicholson
const EmptyList = () => <React.Fragment />;
function ListManager(props) {
const items = props.items;
const isEmpty = items && items.length <= 0;
return isEmpty
? <EmptyList />
: <ItemList items={items} />;
}
function App() {
const collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
return <ListManager items={collection} />;
}
ReactDOM.render(App(), document.getElementById('app'));
我觉得这段代码比第一段好多了。审阅者可以看到代码背后的人是如何思考如何面对问题、限制以及解决问题的。
总结
正如我上面几段话所写,专业的程序员必须赋予代码意义。编程任何人都可以做到,但如何以合理的方式进行编程只是专业人士的职责所在。
你觉得这篇文章的练习怎么样?
希望它能对你有所帮助,或者只是希望你读得开心。