Search code examples
reactjsreact-nativeselectreact-routerdropdown

React Dynamic Filtering to Filter the Card Component


I am new to react, I am working on a project. I need little help regarding the filtering of the data. There are two filters one-: State and Location. The location is dependent on State, which is working fine, but after that, I want to filter my card component i.e VideoCategory card basis on above-selected value. There are three levels of filtering and for the third level, the filtering is not working. Please, anyone, help me out, as I am trying to fix this issue from last two days.

import React, { useState, useEffect } from "react";
import Menu from "../common/Menu";

import { Form, Container, Row, Col } from "react-bootstrap";
import {
  getVideosBasedOnCategories,
  getAllStates,
} from "./helper/userApiCalls";
import VideoCard from "../common/VideoCard";

const CategoryVideos = ({ match }) => {
  const [videoCategory, setVideoCategory] = useState([]);
  const [selectState, setSelectState] = useState([]);
  const [selectLocation, setSelectLocation] = useState([]);

  let location="";

  const preload = (categoryId) => {
    getVideosBasedOnCategories(categoryId).then((data) => {
      if (data.error || !data) {
        console.log(data.error);
        return <h1>No Data to Show Now</h1>;
      } else {
        setVideoCategory(...videoCategory, data);
      }
    });
  };


  //Intial Loading
  useEffect(() => {
    preload(match.params.categoryId);
    getAllStateForSelect();
  }, []);


  //getting data for first Select Component from API
  const getAllStateForSelect = () => {
    getAllStates().then((data) => {
      console.log(data);
      if (data.error) {
        return console.log(data.error);
      } else {
        setSelectState(...selectState, data);
      }
    });
  };

  const handleChange = (event) => {
    console.log(event.target.value);
    setSelectLocation(event.target.value);
  };


  const onLocationChange=(event)=>{
    location = event
    console.log(location)
  }


  //Storing Location into Option for Second Select
  const onSplit = (x) => {
    var arr = [];
    for (let i = 0; i < x.citynames.length; i++) {
      arr.push(
        <option key={i} value={x.citynames[i]}>
          {x.citynames[i]}
        </option>
      );
    }
    return arr;
  };

  return (
    <div>
      <Menu />
      <Container style={{ marginTop: "200px" }}>
        <Form>
          <Form.Group controlId="exampleForm.SelectCustom">
            <Form.Label>Select State</Form.Label>
            <Form.Control
              as="select"
              onChange={handleChange.bind(selectState[0])}
              custom
            >
              {selectState.map((data, index) => (
                <option name="setmap" key={index} value={data._id}>
                  {data.statename}
                </option>
              ))}
            </Form.Control>
          </Form.Group>
        </Form>
        <Form>
          <Form.Group controlId="exampleForm.SelectCustom">
            <Form.Label>Select Location</Form.Label>
            <Form.Control
              as="select"
              onChange={(e) => onLocationChange(e.target.value)}
              custom
            >
              {selectState
                .filter((selectState) => selectState._id.includes(selectLocation))
                .map((e) => onSplit(e))}
            </Form.Control>
          </Form.Group>
        </Form>
        <Row>
          {videoCategory.filter(videocard=>videocard.location.includes(location.toString()))
            .map((videocard) => {
              return (

                <Col lg={4} xs={12} md={12} className="py-3 px-3">
                  <VideoCard videoCategory={videocard} 
                              />
                </Col>
              );
            })}
        </Row>
      </Container>
    </div>
  );
};

export default CategoryVideos;

VideoCategory File

import React, { Fragment,useEffect,useState } from "react";
import { Card, Button, Container, Row, Col } from "react-bootstrap";
import {getStateById} from '../user/helper/userApiCalls'

const VideoCard = ({ videoCategory }) => {
    const [state,setState] = useState("");
    const [city,setCity] = useState("");
  //const { name, link, description } = videoCategory;
  const getStateByFromVideoId = (stateId)=>{
    getStateById(stateId).then((data)=>{
        console.log(data)
        if(data.error){
            return  console.log(data.error)
        }
        else{

           setState(data.statename)
        }
    })
  }

  useEffect(() => {
    getStateByFromVideoId(videoCategory.state);

  }, []);
  return (
    <Container fluid>
      <iframe
        src={videoCategory.link}
        width="300px"
        height="300px"
        id="myId"
        className="myClassname"
        display="initial"
        position="relative"
        allowfullscreen="allowfullscreen"
      ></iframe>

      <Card style={{ width: "300px", }}>
        <Card.Body>
          <Card.Title>{videoCategory.name}</Card.Title>
          <Card.Text>{videoCategory.description}</Card.Text>
          <Card.Text>{state}</Card.Text>
          <Card.Text>{videoCategory.location}</Card.Text>
          <Button variant="primary">Go somewhere</Button>
        </Card.Body>
      </Card>
    </Container>
  );
};

export default VideoCard;




 **UPDATE**
The API structure for State, which will reflect in card, the location is hardcoded, it doesn't have any id.


  {
            "_id": "5eb59d177693b6f99404f4c6",
            "link": "https://www.youtube.com/embed/NEIwl93Yr8o",
            "description": "LifeStyle",
            "name": "Testing",
            "state": "5eb564ec7693b6f99404f4c5",
            "category": "5ead7555fb5c440f458e625b",
            "location": "Kondapur",
            "createdAt": "2020-05-08T17:55:35.731Z",
            "updatedAt": "2020-05-08T18:28:43.635Z",
            "__v": 0
        },
** The Filter of State and location(citynames) is :**
    {
        "citynames": [
            "ABC",
            "EFG"
        ],
        "_id": "5eb2ad8b554215be68773cf1",
        "statename": "Madras",
        "createdAt": "2020-05-06T12:28:59.149Z",
        "updatedAt": "2020-05-06T12:28:59.149Z",
        "__v": 0
    },

Solution

  • Here's i change some code, but there's also some notes i need to confirm first

    import React, { useState, useEffect } from "react";
    import Menu from "../common/Menu";
    
    import { Form, Container, Row, Col } from "react-bootstrap";
    import {
      getVideosBasedOnCategories,
      getAllStates,
    } from "./helper/userApiCalls";
    import VideoCard from "../common/VideoCard";
    
    const CategoryVideos = ({ match }) => {
      const [videoCategory, setVideoCategory] = useState([]);
      const [apiStates, setApiStates] = useState([])
      const [selectedState, setSelectedState] = useState(null);
      // Change default value to '' i think
      const [selectedLocation, setSelectedLocation] = useState(null);
    
      const preload = (categoryId) => {
        getVideosBasedOnCategories(categoryId).then((data) => {
          if (data.error || !data) {
            console.log(data.error);
            return <h1>No Data to Show Now</h1>;
          } else {
            setVideoCategory(...videoCategory, data);
          }
        });
      };
    
    
      //Intial Loading
      useEffect(() => {
        preload(match.params.categoryId);
        getAllStateForSelect();
      }, []);
    
    
      //getting data for first Select Component from API
      const getAllStateForSelect = () => {
        getAllStates().then((data) => {
          console.log(data);
          if (data.error) {
            return console.log(data.error);
          } else {
            setApiStates(...apiStates, data);
            // remove this line
            // setSelectedLocation(data[0])
          }
        });
      };
      
      const onStateChange = event => {
        setSelectedState(event.target.value)
      }
    
      const onLocationChange= event => {
        setSelectedLocation(event.target.value);
      }
    
    
      //Storing Location into Option for Second Select
      const onSplit = (x) => {
        var arr = [];
        for (let i = 0; i < x.citynames.length; i++) {
          arr.push(
            <option key={i} value={x.citynames[i]}>
              {x.citynames[i]}
            </option>
          );
        }
        return arr;
      };
    
      return (
        <div>
          <Menu />
          <Container style={{ marginTop: "200px" }}>
            <Form>
              <Form.Group controlId="exampleForm.SelectCustom">
                <Form.Label>Select State</Form.Label>
                <Form.Control
                  as="select"
                  onChange={onStateChange}
                  custom
                >
                  {apiStates.map((data, index) => (
                    <option name="setmap" key={index} value={data._id}>
                      {data.statename}
                    </option>
                  ))}
                </Form.Control>
              </Form.Group>
            </Form>
            <Form>
              <Form.Group controlId="exampleForm.SelectCustom">
                <Form.Label>Select Location</Form.Label>
                <Form.Control
                  as="select"
                  onChange={onLocationChange}
                  custom
                >
                  {apiStates
                    .filter(apiState => apiState._id === selectedState)
                    .map(value => onSplit(value))}
                </Form.Control>
              </Form.Group>
            </Form>
            <Row>
            // I'm curious about the location, is it array of string ?
              {videoCategory.filter(videocard => videocard.location === selectedLocation))
                .map((videocard) => {
                  return (
                    <Col lg={4} xs={12} md={12} className="py-3 px-3">
                      <VideoCard videoCategory={videocard} />
                    </Col>
                  );
                })}
            </Row>
          </Container>
        </div>
      );
    };
    
    export default CategoryVideos;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>