admin管理员组

文章数量:1335877

I am trying to set a simple search operation in a user interface as shown below:

I have a total of 70 react-strap cards and each card contain a vessel with name, type and an image. I would like to search the name of the vessel and have the card related to that vessel to pop-up. All my images are currently contained inside the external database Contentful. Below the fields of interests:

The problem is that I don't know how to write a search function that locate a specific value of a list.

Below the code:

SideBar.js

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

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

    async ponentDidMount() {
        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={shippanylogo.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 ma
                                </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>
        );
    }
}

What I have done so far:

1) I tried different bination with the filter function and I think I am close. The problem is that when I operate the search nothing happens and in order to find the card of the vessel I want, I have to scroll down until I find it.

I am running out of ideas and if you see something I didn't catch point me in the right direction for solving this issue.

I am trying to set a simple search operation in a user interface as shown below:

I have a total of 70 react-strap cards and each card contain a vessel with name, type and an image. I would like to search the name of the vessel and have the card related to that vessel to pop-up. All my images are currently contained inside the external database Contentful. Below the fields of interests:

The problem is that I don't know how to write a search function that locate a specific value of a list.

Below the code:

SideBar.js

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

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

    async ponentDidMount() {
        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.panylogo.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 ma
                                </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>
        );
    }
}

What I have done so far:

1) I tried different bination with the filter function and I think I am close. The problem is that when I operate the search nothing happens and in order to find the card of the vessel I want, I have to scroll down until I find it.

I am running out of ideas and if you see something I didn't catch point me in the right direction for solving this issue.

Share Improve this question edited Mar 6, 2020 at 20:32 Emanuele asked Mar 6, 2020 at 19:25 EmanueleEmanuele 2,4148 gold badges38 silver badges88 bronze badges 4
  • Are you getting anything in your console.log(ship) statement? – LHM Commented Mar 6, 2020 at 19:34
  • @LHM, thanks for reading the question :) . Basically I get all the ships from the console log. However the search (or filter does not work properly. I made this if that could be useful to better understand my final goal. – Emanuele Commented Mar 6, 2020 at 19:51
  • Basically I have a total of 80 cards, each card has a name, vessel type and image. I would like to search (or filter) the name of the vessel. – Emanuele Commented Mar 6, 2020 at 19:53
  • As an alternative to creating your own search, have you considered using Algolia? They provide a free tier and an excellent React client library: algolia./doc/guides/building-search-ui/getting-started/react – Gordon Burgett Commented Mar 9, 2020 at 14:07
Add a ment  | 

2 Answers 2

Reset to default 3

You're close! I would add a field to your state called 'searchText' and then create a method to filter based on that searchText state item.

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

Then just map over those values to render the cards that match the search text. The cards will update each time the searchText value updates.

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

React is famous for re-usable ponent. You will have all the data of these vessels in an array. You will loop through the array and render the items with card ponent.And when you search for the specific card you want that vessel to pop out on top.

There are two ways to do it:

You have to run through the array, find the index of that vessel and do whatever it takes to manipulate your array and to make that item at top and re-render your list.

Alternatively render one more ponent on top of your vessel list as user clicks the search button. You just have to find the item index and render it. This way you don't have to deal with array manipulation. It doesn't matter if you have 80 or 1000 cards.

Please checkout official documentation for array methods, for array slicing and splice. Hope this is what you are looking for. If you need further help, ment please.

本文标签: javascriptHow to properly search in a list in ReactJSStack Overflow