【问题标题】: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} />)
          }

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

【问题讨论】:

    标签: javascript reactjs uisearchbar conditional-rendering


    【解决方案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,它可以按照您的描述进行操作(至少我是这么理解的):)
    猜你喜欢
    • 2019-04-04
    • 2019-07-27
    • 2022-01-17
    • 2019-03-25
    • 2021-05-01
    • 1970-01-01
    • 2020-12-20
    • 2020-12-10
    相关资源
    最近更新 更多