繁体   English   中英

过滤器 vs 映射 reactjs 和 jsx

[英]filter vs map reactjs and jsx

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

在组件的渲染方法中,当我使用.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会抛出这个错误 vs map react 和.map有什么独特之处吗? 两者都返回一个数组。

Array.filter不允许您将数据转换为组件。 这就是Array.map的工作。

您应该先过滤,然后链接 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 ,尽管这“不太好”,因为当 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} />
      );
    })
}

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

在使用map()的第一个示例中,您将返回一个在 DOM 中呈现的 React 组件数组。 您正在将数组中的每个普通 JavaScript 对象转换(映射)为 React 组件。 事实上,如果条件book.shelf === shelf为假,您还将在结果数组中返回一些undefined元素。 您的数组可能看起来像[<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 中呈现它们,因此会引发错误。

如果您只想对数组使用一次传递,则可以使用 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可以使代码更易于阅读。

我的答案似乎不错,但我需要使用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} />
      );
    })
}

我也面临同样的错误。 然后,我还将我的map方法包装在filter方法上,这有助于我解决错误并将其作为反应有效子项接受。

<ul className="menu">
            {navigationLinks?.filter((eachNavigation) => {
              if (eachNavigation.select.length < 1) {
                return eachNavigation;
              }
            }).map((eachNavigation, index) => {
              return (
                <li key={index} className="menu__list menu__list--noSelect">
                  <a href={eachNavigation.link}>{eachNavigation.title}</a>
                </li>
              )
            })
            }
          </ul>

 <ul className="menu"> {navigationLinks?.filter((eachNavigation) => { if (eachNavigation.select.length < 1) { return eachNavigation; } }).map((eachNavigation, index) => { return ( <li key={index} className="menu__list menu__list--noSelect"> <a href={eachNavigation.link}>{eachNavigation.title}</a> </li> ) }) } </ul>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM