如何对过滤器方法的结果进行条件渲染?反应

Posted

技术标签:

【中文标题】如何对过滤器方法的结果进行条件渲染?反应【英文标题】:how can i make a conditional rendering to a result from filter method? react 【发布时间】:2021-12-28 20:10:27 【问题描述】: 我有一个父组件,它将所有可供出租的资产传递给一个子组件并渲染它...在同一个组件中我有一个搜索栏,它应该使搜索更容易,我希望因此的输入,呈现与搜索匹配的特定卡片.. 如果在搜索栏中没有插入任何内容,它会呈现所有资产,如果用户键入资产的名称并且它匹配一个或多个资产,它将呈现匹配的资产。

这是我的代码..

class AllAssets extends Component 

  state = 
    cards: [],
    searchField: ''
  

  async componentDidMount() 
    const  data  = await cardService.getAllCards();
    if (data.length > 0) this.setState( cards: data );
  

  addToFavorites = (cardId, userId) => 
    saveToFavorites(cardId, userId)
    toast.error("The asset was added to your favorites.")
  

  render() 

    const  cards, searchField  = this.state;
    const user = getCurrentUser();

    const filteredAssets = cards.filter(card => (
      card.assetName.toLowerCase().includes(searchField.toLowerCase())

    ))
    console.log(filteredAssets);

    return (
      <div className="container">
        <SearchBox placeholder="Enter asset name..."
          handleChange=(e) => this.setState( searchField: e.target.value )
        />
        <PageHeader>Assets available for rent</PageHeader>
        <div className="row">
          <div className="col-12 mt-4">
            cards.length > 0 && <p>you can also add specific assets to your favorites and get back to them later...</p>
          </div>
        </div>
        <div className="row">
          cards.filteredAssets === true ? cards.map(card => <CardPublic addToFavorites=this.addToFavorites card=filteredAssets user=user key=card._id />) :
            cards.map(card => <CardPublic addToFavorites=this.addToFavorites card=card user=user key=card._id />)
          
        </div>
      </div >
    );
  


export default AllAssets;

我尝试使用三元运算符,但不起作用..

 cards.filteredAssets === true ? cards.map(card => <CardPublic addToFavorites=this.addToFavorites card=filteredAssets user=user key=card._id />)
 : cards.map(card => <CardPublic addToFavorites=this.addToFavorites card=card user=user key=card._id />)
          

在控制台中结果很好.. 非常感谢您提前...

【问题讨论】:

【参考方案1】:

您的代码中没有 cards.filteredAssets 这样的东西。有cards 数组,然后有filteredAssets 数组(这是cards 数组上的过滤函数的结果)。所以,cards.filteredAssets 不存在,所以它是假的 (FALSE),绝不是 TRUE。

使用严格相等运算符 (===) filteredAssets 永远不会等于truefilterdAssetsArraytrueBoolean。类型不一样,所以在第一步相等会说“不相等”(ECMAScript 2022 specification 7.2.16)

你可以使用

!!filteredAssets.length === true

(请注意为什么!!filteredAssets.length 有效,但只是!!filteredAssets 无效:

第一个! 将值强制为Boolean(真-> 假,假-> 真,因为! 是逻辑否定),第二个! 只是否定Boolean(即被否定),从而产生真->真,假->假最终结果; 因为[] 是真的,所以!!filteredAssets 总是会返回真

const arr = []
console.log("arr:", arr, !!arr)

)

或者干脆

filteredAssets.length // 0 length is falsy (FALSE), any other length is truthy (TRUE)

或者您可以在创建filteredAssets 数组时简单地处理整个事情(因此,如果filter 函数的结果长度为0,那么您应该让它等于cards) .

但是

如果可能的话,用函数式组件(不是类组件)来做整个事情,使用钩子(useStateuseEffect 等),你会得到一个更好看的组件。 请不要称组件为“父亲”和“儿子”;公认的命名约定说它们是“父母”(如果需要,甚至是“祖父母”)和“孩子”(是的,“孙子”;简单地说:如果您不交流,人们将无法理解您在说什么使用广泛接受的条款。)

编辑

在 OP 发表评论后,我添加了这个 sn-p:

const  useState, useEffect  = React

// custom hook for mocking API data
const useUsersApi = () => 
  const [response, setResponse] = useState([]);

  // only runs once
  useEffect(() => 
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(res => res.json())
      .then(json => 
        setResponse(() => json.map((id, name, username, email) => (id, name, username, email)))
      )
  , []);

  return response;
;

const SearchBar = ( onSearch ) => 
  return (
    <div>
      Search by name:
      <input
        type="text"
        onInput=(e) => onSearch(e.target.value)
      />
    </div>
  )


const UserCard = ( userData ) => 
  return (
    <div
      className="card"
    >
      <h3>userData.name</h3>
      <ul>
        
          Object.entries(userData).map(([key, val]) => 
            return (
              <li
                key=key
              >
                key: val
              </li>
            )
          )
        
      </ul>
    </div>
  )


const App = () => 
  const users = useUsersApi()
  const [searchString, setSearchString] = useState('')
  const [filteredUsers, setFilteredUsers] = useState([])

  const onSearchInput = (val) => 
    setSearchString(() => val)
  
  
  const filterUsersByName = (s) => 
    return users.filter(( name ) => name.toLowerCase().indexOf(s.toLowerCase()) !== -1)
  

  useEffect(() => 
    setFilteredUsers(() => filterUsersByName(searchString))
  , [searchString, users])
 
  return (
    <div
      className="container"
    >
      <SearchBar
        onSearch=onSearchInput
      />
      
        filteredUsers.map(user => 
          return (
            <UserCard
              userData=user
              key=user.id
            />
          )
        )
      
    </div>
  )


ReactDOM.render(
  <App />,
  document.getElementById('root')
);
html, body 
  margin: 0;
  padding: 0;


.container 
  padding: 8px 16px;


.card 
  margin-top: 10px;
  margin-bottom: 10px;
  border: 1px solid black;
  padding: 0px 16px;
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

我希望这个 sn-p 对您有更多帮助:我使用带有钩子的功能组件对虚构用户名进行不区分大小写的过滤。

【讨论】:

嘿,格雷格,感谢您的友好回答,但实际上它并没有解决我的问题..您能更具体一点并尝试提供更多帮助吗?我看得出来你知识渊博 @juniorkim 我添加了一个 sn-p,它可以按照您的描述进行操作(至少我是这么理解的):)

以上是关于如何对过滤器方法的结果进行条件渲染?反应的主要内容,如果未能解决你的问题,请参考以下文章

R Shiny app - 渲染数据表条件

反应中的双重条件渲染?

过滤器如何处理会话

在 Shiny 的反应函数中使用 dplyr 条件过滤器

Servlet过滤器,Servlet过滤器创建和配置

闪亮的动态/条件过滤选择多个输入(selectizeInput,多个= TRUE)