【问题标题】:How to properly search in a list in ReactJS如何在 ReactJS 的列表中正确搜索
【发布时间】:2020-06-19 13:31:18
【问题描述】:

我正在尝试在用户界面中设置一个简单的搜索操作,如下所示:

我总共有 70 个react-strapcards,每张卡片都包含一个带有名称、类型和图像的容器。我想搜索船只的名称并弹出与该船只相关的卡片。我所有的图像当前都包含在外部数据库Contentful 中。以下是感兴趣的领域:

问题是我不知道如何编写一个查找列表特定值的搜索函数。

代码下方:

SideBar.js

import React from 'react';
import Client from '../Contentful';
import SearchVessel from '../components/SearchVessel';

class Sidebar extends React.Component {
    state = {
        ships: [],
    };

    async componentDidMount() {
        let response = await Client.getEntries({
            content_type: 'cards'
        });
        const ships = response.items.map((item) => {
            const {
                name,
                slug,
                type
            } = item.fields;
            return {
                name,
                slug,
                type
            };
        });

        this.setState({
            ships
        });
    }

    getFilteredShips = () => {
        if (!this.props.activeShip) {
            return this.state.ships;
        }
        let targetShip = this.state.ships.filter(
            (ship) => this.props.activeShip.name === ship.name
        );
        let otherShipsArray = this.state.ships.filter((ship) => this.props.activeShip.name !== ship.name);
        return targetShip.concat(otherShipsArray);
    };

    render() {
        return (
            <div className="map-sidebar">
                {this.props.activeShipTypes}

                <SearchVessel />

                <pre>
                    {this.getFilteredShips().map((ship) => {
                        console.log(ship);
                        return (
                            <Card className="mb-2">
                                <CardImg />
                                <CardBody>
                                    <div className="row">
                                        <img
                                            className="image-sizing-primary"
                                            src={ship.companylogo.fields.file.url}
                                            alt="shipImage"
                                        />
                                    </div>
                                    <div>
                                        <img
                                            className="image-sizing-secondary"
                                            src={ship.images.fields.file.url}
                                            alt="shipImage"
                                        />
                                    </div>
                                    <CardTitle>
                                        <h3 className="thick">{ship.name}</h3>
                                    </CardTitle>
                                    <CardSubtitle>{ship.type}</CardSubtitle>
                                    <CardText>
                                        <br />
                                        <h6>Project Details</h6>
                                        <p>For a description of the project view the specification included</p>
                                    </CardText>
                                    <Row style={{ marginTop: '20px' }}>
                                        <div className="buttoncontainer">
                                            <div className="btn btn-cards">
                                                <a
                                                    className="buttonLink"
                                                    download
                                                    href={ship.projectnotes.fields.file.url}
                                                >
                                                    Project Notes
                                                </a>
                                            </div>
                                            <div className="btn btn-cards">
                                                <a className="buttonLink" href={ship.abstract.fields.file.url}>
                                                    Abstract
                                                </a>
                                            </div>
                                        </div>
                                    </Row>
                                </CardBody>
                            </Card>
                        );
                    })}
                </pre>
            </div>
        );
    }
}

export default Sidebar;

VesselSearch.js

import React, { Component } from 'react';

export default class SearchVessel extends Component {
    render() {
        const { value, handleSubmit, handleChange } = this.props;

        return (
            <React.Fragment>
                <div className="container">
                    <div className="row">
                        <div className="col-10 mx-auto col-md-8 mt-5 text-center">
                            <h4 className="text-slanted text-capitalize">Search for Vessel</h4>
                            <form className="mt-4" onSubmit={handleSubmit}>
                                <label htmlFor="search" className="text-capitalize">
                                    type vessel separated by comma
                                </label>
                                <div className="input-group">
                                    <input
                                        type="text"
                                        name="search"
                                        placeholder="Type name of vessel here"
                                        className="form-control"
                                        value={value}
                                        onChange={handleChange}
                                    />
                                    <div className="input-group-append">
                                        <button type="submit" className="input-group-text bg-primary text-white">
                                            <i className="fas fa-search" />
                                        </button>
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </React.Fragment>
        );
    }
}

到目前为止我做了什么:

1) 我尝试了过滤功能的不同组合,我认为我很接近。问题是,当我进行搜索时,什么也没有发生,为了找到我想要的船只卡,我必须向下滚动直到找到它。

我的想法已经不多了,如果您看到我没有抓住的东西,可以为我指出解决此问题的正确方向。

【问题讨论】:

  • 您的 console.log(ship) 语句中是否有任何内容?
  • @LHM,感谢您阅读问题:)。基本上我从控制台日志中得到了所有的船只。但是,搜索(或过滤器无法正常工作。如果这有助于更好地理解我的最终目标,我就创建了this
  • 基本上我一共有80张卡片,每张卡片都有名字、容器类型和图片。我想搜索(或过滤)船只的名称。
  • 除了创建自己的搜索之外,您是否考虑过使用 Algolia?他们提供免费层和优秀的 React 客户端库:algolia.com/doc/guides/building-search-ui/getting-started/react

标签: javascript reactjs contentful


【解决方案1】:

React 以可重用组件而闻名。您将在一个数组中拥有这些船只的所有数据。您将遍历数组并使用卡片组件渲染项目。当您搜索特定卡片时,您希望该容器弹出顶部。

有两种方法:

您必须遍历数组,找到该容器的索引,并尽一切可能来操作您的数组并将该项目置于顶部并重新呈现您的列表。

当用户单击搜索按钮时,或者在您的船只列表顶部再呈现一个组件。您只需要找到项目索引并呈现它。这样您就不必处理数组操作。如果您有 80 或 1000 张卡,则无关紧要。

请查看有关数组方法、数组切片和拼接的官方文档。 希望这是您正在寻找的。如果您需要进一步的帮助,请发表评论。

【讨论】:

  • 非常感谢您阅读这个问题:)。您能否包含一些代码以与我现有的代码集成,以便我更好地理解您的解决方案?
  • 我可以得到你的 github repo 的链接吗?
  • 不幸的是,这是一个大项目,无法真正创建沙箱,我也不能要求您查看整个代码,但我感谢您提供。我确实更新了问题并添加了之前缺少的 VesselSearch.js。也许这也有帮助?
  • 您不必创建沙箱!您只需将其推送到 github 存储库。
【解决方案2】:

你已经接近了!我会在您的状态中添加一个名为“searchText”的字段,然后创建一个基于该 searchText 状态项进行过滤的方法。

getFilteredShips = () => this.state.ships.filter(s => s.name.includes(this.state.searchText)

然后只需映射这些值以呈现与搜索文本匹配的卡片。每次 searchText 值更新时,卡片都会更新。

this.getFilteredShips().map(ship => ..........

【讨论】:

  • 感谢您阅读问题。负责操作搜索的实体是&lt;SearchVessel /&gt;,但截至目前没有关联的属性。我认为您的解决方案很好,但我如何将其链接到 &lt;VesselSearch /&gt;
  • 我更新了问题并添加了 VesselSearch.js,如果这可能有用的话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
  • 2022-10-07
  • 1970-01-01
  • 1970-01-01
  • 2020-01-25
  • 2011-04-19
  • 2020-05-13
相关资源
最近更新 更多