Reactjs - фильтрация данных из ответа API - PullRequest
0 голосов
/ 06 февраля 2020

Я работаю над reactjs проектом, довольно новым для этой технологии. У меня есть ответ API-данных, в котором проводится различие между продуктами, т. Е. Внутренними продуктами (которые загружаются из приложения) и внешними продуктами (которые сканируются с других веб-сайтов). Для большей ясности ответ API json выглядит следующим образом.

[
    {
        "id": 0,
        "title": "TestProductForAzure",
        "description": null,
        "owner": "Seeded Company",
        "url": "http://localhost:54729/api/product/3",
        "type": "Internal",
        "rank": 0,
    },
    {
        "id": 0,
        "title": "OAS",
        "description": null,
        "owner": null,
        "url": "https://support.example.com/en-ae",
        "type": "External",
        "rank": 0,
    },
    {
        "id": 0,
        "title": "OAS",
        "description": null,
        "owner": null,
        "url": "https://support.example.com/en-al",
        "type": "External",
        "rank": 0,
    }

Как видите, объект type помогает мне различать все продукты в ответе API. Я хочу поставить фильтр на него, так как когда пользователь выбирает из выпадающего списка Внутренний, он будет отображать только внутренние продукты, а если пользователь выбирает Внешний, он будет отображать только внешние продукты.

То, что я пробовал до сих пор, ниже.

SearchActions

import {
  SEARCH_PRODUCTS,
  FETCH_PRODUCTS,
  LOADING,
  PAGINATE,
  KEYWORD
} from "./types";
import axios from "axios";
import { results } from "./data/result";
import { store } from "../_helpers/store";
import { userService } from "../_services";

import { apiBaseUrl } from "../config.example";

const token = userService.getToken();

export const searchProduct = text => dispatch => {
  dispatch({
    type: SEARCH_PRODUCTS,
    payload: text
  });
};

export const fetchProducts = text => dispatch => {
  console.log("Called from ", text);

  const api = `/Search?searchString=${text}`;

  axios
    .get(apiBaseUrl + api, { headers: { Authorization: `Bearer ${token}` } })

    .then(res => {
      console.log("hello", api);
      try {
        dispatch({
          type: FETCH_PRODUCTS,
          payload: res
        });
      } catch (err) {
        console.log("error", err);
      }
    });
};

export const saveKeyword = text => dispatch => {
  const api = `/search/${text}`;

  axios
    .get(apiBaseUrl + api, { headers: { Authorization: `Bearer ${token}` } })
    .then(res => {
      console.log("Keyword Api called");
      try {
        dispatch({
          type: KEYWORD,
          payload: res
        });
      } catch (err) {
        console.log("Error in Keyword", err);
      }
    });
};

export const paginate = currentPage => dispatch => {
  dispatch({
    type: PAGINATE,
    payload: currentPage
  });
  dispatch(fetchProducts("paginate"));
};

export const setLoading = () => {
  return {
    type: LOADING
  };
};

Searchbar.jsx

import React from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import {
  searchProduct,
  fetchProducts,
  setLoading,
  saveKeyword
} from "../../../_actions/search.action";
import Loader from "react-loader-spinner";

class SearchBar extends React.Component {
  handleInputChange = e => {
    e.preventDefault();
    this.props.searchProduct(e.target.value);
  };

  onClick = e => {
    console.log("I am " + this.props.text);
    console.log("Search button clicked");
    this.props.saveKeyword(this.props.text);
    this.props.fetchProducts(this.props.text);
    // this.props.setLoading();
  };

  render() {
    const { text, loading } = this.props;

    return (
      <div className="s130">
        <form
          onSubmit={e => {
            e.preventDefault();
          }}
        >
          <div className="inner-form">
            <div className="input-field first-wrap">
              <div className="svg-wrapper">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="auto"
                  height="auto"
                  viewBox="0 0 24 24"
                >
                  <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z">
                    {" "}
                  </path>
                </svg>
              </div>
              <input
                id="search"
                type="text"
                value={text}
                placeholder="What are you looking for?"
                onChange={this.handleInputChange}
                ref={input => (this.textInput = input)}
              />
            </div>
            <div className="input-field second-wrap">
              <Link to={`/dashboard/search?q=${text}`}>
                <button
                  className="btn-search"
                  type="button"
                  onClick={this.onClick}
                >
                  {" "}
                  SEARCH{" "}
                </button>
              </Link>
            </div>

            {loading ? "Searching" : ""}

            {this.pr}
          </div>
        </form>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  text: state.product.text,
  loading: state.product.loading
});

export default connect(mapStateToProps, {
  searchProduct,
  fetchProducts,
  setLoading,
  saveKeyword
})(SearchBar);

Search-results-container.jsx

import React from "react";
import queryString from "query-string";
import { connect } from "react-redux";
import SearchResult from "./search-results";
import { results } from "../../../_actions/data/result";
import Select from "react-select";
import "react-loader-spinner/dist/loader/css/react-spinner-loader.css";
import Loader from "react-loader-spinner";
import SearchBar from "./search-bar";
import { fetchProducts, searchProduct } from "../../../_actions/search.action";
import { useSelector, useDispatch } from "react-redux";

class SearchResultContainer extends React.Component {
  componentDidMount() {
    const query = queryString.parse(this.props.location.search).q;
    console.log("Location Props", this.props.location.search);

    this.props.searchProduct(query);
    this.props.fetchProducts(query);
  }

  componentWillReceiveProps(nextProps) {
    console.log("nextProps", nextProps);
    // if (nextProps.query !== this.props.query) {
    //   this.setState({ query: nextProps.query });
    //   return this.searchRepositories(nextProps.query);
    // }
  }

  render() {
    const { loading } = this.props;
    const str = this.props.location.search;
    const res = str.split("?q=");
    console.log("PROS", this.props);

    const companies = [
      {
        label: "Internal",
        value: "Internal"
      },
      {
        label: "External",
        value: "External"
    ];

    return loading ? (
      <div class="row"></div>
    ) : (
      <React.Fragment>
        <div className="row">
          <div className="col-sm-2" />
          <div className="col-sm-8">
            <div class="container bootstrap snippet">
              <div class="row">
                <div class="col-lg-12">
                  <div class="ibox float-e-margins">
                    <div class="ibox-content">
                      <h2>We are Fetching:{res}</h2>
                      <small>
                        Request time (5-10 seconds): Please be patient, this may
                        take sometime, as we are gathering information
                      </small>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <SearchBar />
//For Internal and External

           <Select options={Select}></Select>

            <br></br>
            <div class="row">
              <Loader
                type="ThreeDots"
                color="#00BFFF"
                height="100"
                width="100"
                timeout={2500}
              ></Loader>
              <SearchResult />
            </div>
          </div>
          <div className="col-sm-2" />
        </div>
      </React.Fragment>
    );
  }
}

const mapStateToProps = state => ({
  loading: state.product.loading
});

export default connect(mapStateToProps, { searchProduct, fetchProducts })(
  SearchResultContainer
);

search-results.jsx

import React from "react";

import { connect } from "react-redux";
import SingleSearchResult from "./single-search-result";
import { results } from "../../../_actions/data/result";

import "react-loader-spinner/dist/loader/css/react-spinner-loader.css";
import Loader from "react-loader-spinner";
import { useSelector, useDispatch } from "react-redux";
import { paginate } from "../../../_actions/search.action";

import Pagination from "./pagination";
import "./test.css";

class SearchResults extends React.Component {
  // onChangePage = data => {
  //   this.setState({
  //     pageLimit: data.pageLimit,
  //     totalPages: data.totalPages,
  //     currentPage: data.page,
  //     startIndex: data.startIndex,
  //     endIndex: data.endIndex
  //   });
  // };

  render() {
    const { products, pagination, paginate } = this.props;

    return (
      <React.Fragment>
        {products.map(result => (
          <SingleSearchResult result={result} />
        ))}

        {/* <Pagination
                  totalRecords={products.length}
                  pageLimit={pageLimit || 2}
                  initialPage={1}
                  pagesToShow={5}
                  onChangePage={this.onChangePage}
                /> */}
        <div class="row">
          <div class="center-block">
            <Pagination
              resultsPerPage={pagination.pageLimit}
              totalResults={10}
              paginate={paginate}
            />
          </div>
        </div>
      </React.Fragment>
    );
  }
}

const mapStateToProps = state => ({
  products: state.product.products,
  pagination: state.product.pagination
});

export default connect(mapStateToProps, { paginate })(SearchResults);

и последние где все мои результаты поиска выглядят так:

singlesearchresult

import React, { useState, useEffect } from "react";
import Rating from "./rating";
import "./test.css";
import { Spinner, Collapse, Card, CardBody } from "reactstrap";
import { detailsProduct } from "../../../_actions/product.details.action";
import { ProductDetails, DoctorProductLocation } from "../../../locations";
import { Link, Redirect } from "react-router-dom";
import { setLoading } from "../../../_actions/search.action";
import Loader from "react-loader-spinner";
import Select from "react-select";
import { GoThumbsdown, GoThumbsup } from "react-icons/go";
import Footer from "../footer";

// import { fetchProducts } from "../../../_actions/search.action";
// import { detailsProduct } from "../../../_actions/product.details.action";

function onClickHandler(id) {
  console.log("calling Details Product", id);
  detailsProduct(id);
}

export default function SingleSearchResult(props) {
  // console.log("PROPS FROM SINGLE SEARCH", props);
  let result = props.result;

  //Collapse For External
  const [collapse, setCollapse] = useState(false);

  const toggle = () => setCollapse(!collapse);

  const loading = () => <Spinner color="success" />;

  // console.log("SINGLE SEARCH PROPS RESULT", result);
  // loading = () => <Spinner color="success" />;
  {
    /* <Loader
            type="ThreeDots"npm
            color="#00BFFF"
            height="100"
            width="100"
            timeout={1000}
          ></Loader> */
  }
  console.log("Length", result.title.slice(0, 3));

  return (
    <div className="row">
      <div className="s130">
        {/* <div class="col-lg-8 col-xs-8 col-sm-12 col-md-7"> */}
        <div className="col-lg">
          <div className="container">
            <div className=""></div>
            {/* Loader Here ibox-content*/}
            {result.type === "Internal" ? (
              <Link
                value={result.productid}
                to={DoctorProductLocation.path}
                onClick={() => onClickHandler(result.productid)}
                //onClickHandler(result.productid)
              >
                <h3 style={{ color: "#1a0dab" }}>
                  {result.title}
                  <hr></hr>
                </h3>
              </Link>
            ) : (
              //Try With OnClick Function
              <a onClick={toggle} target="_blank">
                <h3 style={{ color: "RED" }}>
                  {result.title}
                  <hr></hr>
                </h3>
              </a>
            )}
            <p className="p1">{result.description}</p>
            {/* //href={result.url} */}
            {/* {result.type == "Article" ? <p>by {result.author}</p> : ""} */}
            {/* <Rating rating={result.rating} /> */}
          </div>

          {/* <a
          href={result.url}
          target={result.url === "External" ? "_blank" : ""}
          // data-toggle="modal"
          // data-target="#aripiprazol"
        >
          {" "}
          <cite class="iUh30">{result.url}</cite>
          <br />
        </a> */}
          {result.type === "Internal" ? (
            <Link
              className="iUh30"
              to={DoctorProductLocation.path}
              onClick={() => onClickHandler(result.productid)}
            >
              {/* <a className="iUh30">{result.url}</a> */}
              {/* <p>DDH PRODUCT</p> */}
            </Link>
          ) : (
            //Try With OnClick Function
            <Collapse isOpen={collapse}>
              <Card style={{ maxWidth: "100%" }}>
                <CardBody>
                  Source:
                  <a className="iUh30" href={result.url} target="_blank">
                    <a>{result.url}</a>
                  </a>
                </CardBody>
              </Card>
              <Card style={{ maxWidth: "100%" }}>
                <CardBody>
                  <a
                    href={result.url + "subscribe"}
                    style={{ color: "#1a0dab" }}
                    target="_blank"
                  >
                    Subscribe
                  </a>
                  <p>{result.description} </p>
                </CardBody>
                <div className="row">
                  <GoThumbsup className="col-6"></GoThumbsup>
                  <GoThumbsdown className="col-6"></GoThumbsdown>
                </div>
              </Card>

              <br></br>
            </Collapse>
          )}

          {/* RANKING */}
          {/* <p className="rank">Visited {result.rank} times</p> */}
        </div>
      </div>
    </div>
  );
}



Как вы можете видеть выше в search-result-container.jsx Я пытался использовать библиотеку реагировать на выбор для раскрывающегося списка, а затем для ответа, но я не имею ни малейшего представления о том, как я могу это сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...