I have two inputs and am trying to have them filter out separate data. I'm using an NPM package for the filter which works great for the first input, as it returns based on any criteria on the card. I need the second input to return based on tags that are added after the fact. I feel like this is a simple answer but I'm a bit new so I can't get this to work. I've tried using context to get the state from any component but either way, I do this I still can't get it to filter. Any feedback or help would be greatly appreciated - thanks :)
Main.jsx
import React from "react";
import axios from "axios";
import { useState, useEffect, useContext } from "react";
import TagProvider from "../context/TagContext";
import { TagContext } from "../context/TagContext";
import Card from "./Card/Card";
import "./Main.scss";
import FilterResults from "react-filter-search";
export default function Main() {
//using state with hooks
const [students, setStudents] = useState([]);
const [value, setValue] = useState("");
const [valueTwo, setValueTwo] = useContext(TagContext);
// axios call to get data
const url = "https://api.hatchways.io/assessment/students";
const getData = () => {
axios
.get(`${url}`)
.then((res) => {
const studentData = res.data.students;
setStudents(studentData);
})
.catch((error) => console.log(`Error: ${error}`));
};
useEffect(() => {
getData();
}, []);
// handleChange function for filter results
let handleChange = (event) => {
const { value } = event.target;
setValue(value);
};
let handleChangeTwo = (event) => {
const { valueTwo } = event.target;
setValueTwo(valueTwo);
};
return (
<>
<TagProvider>
<div className="main">
<input
type="text"
className="main__search"
value={value}
placeholder="Search by name"
onChange={handleChange}
/>
<input
type="text"
className="main__search"
value={valueTwo}
placeholder="Search by tag"
onChange={handleChangeTwo}
/>
<FilterResults
value={value}
data={students}
renderResults={(results) => (
<div className="main__container">
{results.map((item) => (
<Card
key={item.id}
email={item.email}
company={item.company}
skill={item.skill}
firstname={item.firstName}
lastname={item.lastName}
grades={item.grades}
pic={item.pic}
/>
))}
</div>
)}
/>
</div>
</TagProvider>
</>
);
}
Card.jsx
import React, { useState, useRef } from "react";
import "./Card.scss";
import Tags from "../Tags/Tags";
import TagProvider from "../../context/TagContext";
export default function Card(props) {
const [setActive, setActiveState] = useState("");
const [setHeight, setHeightState] = useState("0px");
const content = useRef(null);
function toggleAccordion() {
setActiveState(setActive === "" ? "active" : "");
setHeightState(
setActive === "active" ? "0px" : `${content.current.scrollHeight}px`
);
}
// convert string to integer
let result = props.grades.map((x) => {
return parseInt(x, 10);
});
// caluclate average function
const average = (nums) => nums.reduce((a, b) => a + b) / nums.length;
const gradeTitle = [
"Test 1:",
"Test 2:",
"Test 3:",
"Test 4:",
"Test 5:",
"Test 6:",
"Test 7:",
"Test 8:",
];
return (
<div>
{/* Card Section */}
<div className="card__container">
<img className="card__image" src={props.pic} alt="avatar" />
<div className="card__container-two">
<div className="card__container-plus">
<h1 className="card__name">
{props.firstname} {props.lastname}
</h1>
<button className="card__button" onClick={toggleAccordion}>
+
</button>
</div>
<div className="card__container-three">
<div className="card__info">Email: {props.email}</div>
<div className="card__info">Company: {props.company}</div>
<div className="card__info">Skill: {props.skill}</div>
<div className="card__info">Average: {average(result)}%</div>
</div>
</div>
</div>
<TagProvider>
<Tags />
</TagProvider>
{/* Card Expansion */}
<div className="accordion">
<div
ref={content}
style={{ maxHeight: `${setHeight}` }}
className="accordion__content"
>
<div className="accordion__tests">
<div className="accordion__test-title">
{gradeTitle.map((title) => (
<div>{title}</div>
))}
</div>
<div className="accordion__test-results">
{result.map((number) => (
<li>{number}%</li>
))}
</div>
</div>
<div
className="accordion__text"
dangerouslySetInnerHTML={{ __html: props.content }}
/>
</div>
</div>
</div>
// </TagContext.Provider>
);
}
Tags.jsx
import React, { useContext } from "react";
import { X } from "react-feather";
import "./Tags.scss";
import { TagContext } from "../../context/TagContext";
import TagProvider from "../../context/TagContext";
export default function Tags() {
const [tags, setTags] = useContext(TagContext);
return (
<TagProvider>
<div className="tags">
<ul className="tags__list">
{tags.map((tag) => (
<li className="tags__tag">
{tag}
<X
className="tags__close-icon"
size="16"
onClick={() => {
setTags([...tags.filter((word) => word !== tag)]);
}}
/>
</li>
))}
</ul>
<div className="tags__form">
<input
className="tags__input"
type="text"
placeholder="Add a tag.."
onKeyPress={(event) => {
if (event.key === "Enter") {
setTags([...tags, event.target.value]);
event.target.value = "";
}
}}
autofocus
/>
</div>
</div>
</TagProvider>
);
}
TagContext.js
import { useState, createContext } from "react";
export const TagContext = createContext();
const TagProvider = (props) => {
const [valueTwo, setValueTwo] = useState([]);
const [tags, setTags] = useState([]);
return (
<TagContext.Provider value={[valueTwo, setValueTwo, tags, setTags]}>
{props.children}
</TagContext.Provider>
);
};
export default TagProvider;