我正在研究一个反应项目来学习反应。
在组件的render方法中,当我使用.map
迭代值并返回组件数组时,一切都按预期工作。
<ol className="books-grid">
{
books && books.map((book, index) => {
if (book.shelf === shelf) {
return (
<Book key={book && book.id ? book.id : index} changeShelf={this.props.changeShelf} book={book} />
);
}
})}
</ol>
但是当我使用filter
时:
<ol className="books-grid">
{
books && books.filter((book, index) => {
if (book.shelf === shelf) {
return (
<Book key={book && book.id ? book.id : index} changeShelf={this.props.changeShelf} book={book} />
);
}
})}
</ol>
我得到了错误(我已研究过)
Uncaught (in promise) Error: Objects are not valid as a React child
我不明白为什么filter
引发此错误与map
?是否有一些独特的反应和.map
?两者都返回一个数组。
答案 0 :(得分:4)
Array.filter
不允许您将数据转换为组件。这是Array.map
的工作。
您应首先过滤,然后在之后链接地图调用:
{
books && books
.filter(book => book.shelf === shelf)
.map((book, index) => {
return (
<Book
key={book && book.id ? book.id : index}
changeShelf={this.props.changeShelf}
book={book} />
);
})
}
如果您想避免第二次通过books
列表,您也可以返回null
,但这样做不太好&#34;因为当它根本不需要做任何工作时,你强迫React渲染null
:
{
books && books
.map((book, index) => {
if (book.shelf !== shelf) {
return null;
}
return (
<Book
key={book && book.id ? book.id : index}
changeShelf={this.props.changeShelf}
book={book} />
);
})
}
答案 1 :(得分:2)
如果您只想在阵列上使用一次传递,则可以使用reduce:
books && books
.reduce(
(all,book, index) => {
if (book.shelf !== shelf) {
return all;
}
return all.concat(
<Book
key={book && book.id ? book.id : index}
changeShelf={this.props.changeShelf}
book={book} />
);
}
,[]
)
然而;我认为使用filter
和map
会使代码更容易阅读。
答案 2 :(得分:1)
React和map()
或filter()
没有什么独特之处。
在使用map()
时的第一个示例中,您将返回在DOM中呈现的React组件数组。您正在将数组中的每个纯JavaScript对象转换(映射)为React组件。事实上,如果条件undefined
是假的,那么您还将在结果数组中返回一些book.shelf === shelf
个元素。您的数组可能看起来像[<Book />, <Book />, undefined, <Book />, undefined]
。这并不是什么大问题,因为React不会渲染虚假值(null
或undefined
元素只会被跳过)。
第二个例子不会返回相同的结果(一个React组件数组),而是一个普通的JavaScript对象数组(类型为book)。这是因为无论您从过滤器函数返回什么内容,它都会被转换为Boolean
值 - true
或false
并且该值将由此决定如果要过滤当前元素。您的.filter()
函数的结果将是这样的(想象shelf === 'Science'
):
Original array: [{ shelf: "Science" }, { shelf: "Thrillers" }, { shelf: "Informatics" }]
Filtered array: [{ shelf: "Science" }]
正如您所看到的,数组中的项不会是React组件(<Book />
),并且React无法在DOM中呈现它们,因此它会抛出错误。
答案 3 :(得分:0)
对我来说答案似乎不错,但我需要使用 includes()
才能工作,使用 toLowerCase()
也可能是个好主意:
{
books && books
.filter(book => book.shelf.toLowerCase().includes(shelf.toLowerCase()))
.map((book, index) => {
return (
<Book
key={book && book.id ? book.id : index}
changeShelf={this.props.changeShelf}
book={book} />
);
})
}