如何对过滤器方法的结果进行条件渲染?反应
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
永远不会等于true
。 filterdAssets
是 Array
,true
是 Boolean
。类型不一样,所以在第一步相等会说“不相等”(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
) .
但是
如果可能的话,用函数式组件(不是类组件)来做整个事情,使用钩子(useState
、useEffect
等),你会得到一个更好看的组件。
请不要称组件为“父亲”和“儿子”;公认的命名约定说它们是“父母”(如果需要,甚至是“祖父母”)和“孩子”(是的,“孙子”;简单地说:如果您不交流,人们将无法理解您在说什么使用广泛接受的条款。)
编辑
在 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,它可以按照您的描述进行操作(至少我是这么理解的):)以上是关于如何对过滤器方法的结果进行条件渲染?反应的主要内容,如果未能解决你的问题,请参考以下文章