filter vs map reactjs和jsx

时间:2018-01-06 01:02:09

标签: javascript reactjs

我正在研究一个反应项目来学习反应。

在组件的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?两者都返回一个数组。

4 个答案:

答案 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} />
    );
  }
  ,[]
)

然而;我认为使用filtermap会使代码更容易阅读。

答案 2 :(得分:1)

React和map()filter()没有什么独特之处。

在使用map()时的第一个示例中,您将返回在DOM中呈现的React组件数组。您正在将数组中的每个纯JavaScript对象转换(映射)为React组件。事实上,如果条件undefined是假的,那么您还将在结果数组中返回一些book.shelf === shelf个元素。您的数组可能看起来像[<Book />, <Book />, undefined, <Book />, undefined]。这并不是什么大问题,因为React不会渲染虚假值(nullundefined元素只会被跳过)。

第二个例子不会返回相同的结果(一个React组件数组),而是一个普通的JavaScript对象数组(类型为book)。这是因为无论您从过滤器函数返回什么内容,它都会被转换为Boolean值 - truefalse并且该值将由此决定如果要过滤当前元素。您的.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} />
      );
    })
}