Few things that need changing in your app.
You are managing your data state inside the Dropdown component, but this data state needs to be shared between the Dropdown, and the Search components, so is best to have it at the root of them, in this case App.
You can then pass the state to the App child components, Dropdown, and Search.
I only focused on the Dropdown component, and the implementation I will show you can be improved, but it will be easy to follow and it will give you a good starting point in my opinion, if not feel free to ask.
App.js
I have move the logic to fetch the data and the state here, and then we pass it to the Dropdown component as props.
You can do the same for the Search component, by creating a search term state for example.
There is an extra useEffect that will take care of updating the filteredData state based on the selectedCountry and selectedVehicle state values.
import "./styles.css";
import Search from "./Search";
import Dropdown from "./Dropdown";
import axios from "axios";
import { useState, useEffect } from "react";
function App() {
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [selectedCountry, setSelectedCountry] = useState("");
const [selectedVehicle, setSelectedVehicle] = useState("");
// ========== FETCHING API DATA ==========
useEffect(() => {
async function getData() {
const res = await axios.get(
"https://612619c7e40e1900170727fe.mockapi.io/api/users"
);
setData(res.data);
}
getData();
}, []);
useEffect(() => {
// If the state changes filter the results
// Quick and dirty filter, you can improve on this
if (selectedCountry || selectedVehicle) {
const found = data.filter(
(item) =>
item.country === selectedCountry || item.vehicle === selectedVehicle
);
setFilteredData(found);
} else {
setFilteredData(data);
}
}, [data, selectedCountry, selectedVehicle]);
return (
<div className="app">
<div className="top-section">
<h1 className="top-title">Filter:</h1>
{/* Pass the state as props to this child component */}
<Dropdown
data={data}
setSelectedCountry={setSelectedCountry}
setSelectedVehicle={setSelectedVehicle}
/>
<div className="user-search">
<Search data={data} />
{/* Render the filtered data */}
{filteredData.map((item) => (
<div className="user-profile" key={item.id}>
<img
src="https://cdn.icon-icons.com/icons2/1378/PNG/512/avatardefault_92824.png"
className="pfp"
alt="user-avatar"
/>
<p style={{ fontWeight: "bold" }}>{item.name}</p>
<p style={{ opacity: "0.8" }}>{item.email}</p>
<p>{item.country}</p>
<p>{item.vehicle}</p>
</div>
))}
</div>
</div>
</div>
);
}
export default App;
Dropdown.js
This component takes data, selectedCountry and selectedVehicle App state as props, and set the values when an option is selected.
// Get the App state as props
function Dropdown({ data, setSelectedCountry, setSelectedVehicle }) {
// FUNCTION TO RESET SEARCH RESULT
function reset() {
// Reset the state values
setSelectedCountry("");
setSelectedVehicle("");
}
// MAIN JSX
return (
<div className="dropdown">
{/* LOADING DROPDOWN OPTIONS */}
<div className="dropdown-options">
<select
className="dd-item"
onChange={(e) => setSelectedCountry(e.target.value)}
>
<option value="">Country</option>
{data.map((item) => (
<option key={item.id} value={item.country}>
{item.country}
</option>
))}
</select>
<select
className="dd-item"
onChange={(e) => setSelectedVehicle(e.target.value)}
>
<option value="">Vehicle</option>
{data.map((item) => (
<option key={item.id} value={item.vehicle}>
{item.vehicle}
</option>
))}
</select>
<button className="reset" onClick={reset}>
RESET
</button>
</div>
</div>
);
}
export default Dropdown;
Search.js
I didn't change much here, other than displaying the cards in the App component.
You don't need to fetch the data again, and pass it as a prop, like I did to the Dropdown component, but I'll leave it up to you to clean it up.
import { useState, useEffect } from "react";
import axios from "axios";
import "./styles.css";
function Search() {
const [searchData, setSearchData] = useState([]);
const [input, setInput] = useState("");
const [output, setOutput] = useState([]);
// =============== GETTING API DATA ===============
useEffect(() => {
async function getData() {
const res = await axios.get(
"https://612619c7e40e1900170727fe.mockapi.io/api/users"
);
setSearchData(res.data);
setOutput(res.data);
}
getData();
}, []);
// ========== MATCHING SEARCH INPUT WITH API DATA ==========
useEffect(() => {
setOutput([]);
searchData.filter((item) => {
if (
item.name.toLowerCase().includes(input.toLowerCase()) ||
item.country.toLowerCase().includes(input.toLowerCase()) ||
item.email.toLowerCase().includes(input.toLowerCase()) ||
item.vehicle.toLowerCase().includes(input.toLowerCase())
) {
setOutput((output) => [...output, item]);
}
});
}, [input]);
function searchInput(e) {
setInput(e.target.value);
}
return (
<input
className="searchbar"
type="text"
placeholder="SEARCH"
onChange={searchInput}
></input>
);
}
export default Search;