When I enter a search term (name, email, username) I want the page to filter out one card from all of the cards based on the search value. I think when the user presses enter, we would need to redirect to a new page to display the card.
I have the code for searchbar and the user component which would be responsible for displaying the single user card. Would we need to use the Redirect feature of the react-router to make this possible? I was struggling with how to implement it as props (the searchItem) also needs to be passed to the User component.
Searchbar.jsx
import React, { useState } from "react"; import UserList from "./UserList"; import User from "./Components/User"; import { Link, Redirect } from "react-router-dom"; const SearchBar = () => { const [searchItem, setSearchItem] = useState(""); const handleChange = (e) => { console.log(e.target.value); setSearchItem(e.target.value); }; const handleSubmit = (e) => { e.preventDefault(); setSearchItem(""); }; return ( <> <div className="searchbar"> <form onSubmit={handleSubmit}> <input name="name" placeholder="Enter Name, Email or Username to Search" type="text" className="search" value={searchItem} onChange={handleChange} /> </form> </div> <UserList /> </> ); }; export default SearchBar;
User.jsx
import React from "react"; import Card from "./Card"; const User = (props) => { return ( <Card key={props.id} name={props.name} email={props.email} website={props.website} phone={props.phone} /> ); }; export default User;
UserList.jsx
import React, { useState, useEffect } from "react"; import Card from "./Components/Card"; const UserList = ({ searchItem }) => { const [data, setData] = useState([]); useEffect(() => { fetch("https://jsonplaceholder.typicode.com/users") .then((response) => response.json()) .then((json) => { console.log(json); const newData = json.map((object) => ({ id: object.id, email: object.email, website: object.website, phone: object.phone, name: object.name, })); // previousData is an empty array and the newData consists of all the users // using the spread operator, we copy the newData into the previousData setData((previousData) => [...previousData, ...newData]); }); }, []); return ( <> <div className="container"> {data.map((info) => { return ( <Card key={info.id} name={info.name} email={info.email} website={info.website} phone={info.phone} /> ); })} </div> </> ); }; export default UserList;
Advertisement
Answer
I don’t think you to need to use react-router here to achieve this.
The type of search you want determines the approach you can take. Do you want the cards to be filtered on each key press or only on form submit?
Currently you have a mix of these two approaches since you have a form
element with an onSubmit
, but you also have an input
element with an onChange
(uncontrolled and controlled).
Here’s a simplified example of a live search, controlled component approach:
const User = (props) => { return <p>{props.name}</p>; }; const UserList = ({ searchItem }) => { const [data, setData] = useState([]); useEffect(() => { fetch("https://jsonplaceholder.typicode.com/users") .then((response) => response.json()) .then((json) => { console.log(json); const newData = json.map((object) => ({ id: object.id, email: object.email, website: object.website, phone: object.phone, name: object.name, })); setData(newData); }); }, []); const filteredUsers = data.filter((user) => { return user.name.includes(searchItem); }); return filteredUsers.map((user) => { return <User key={user.id} name={user.name} />; }); }; const SearchBar = () => { const [searchItem, setSearchItem] = useState(""); const handleChange = (e) => { console.log(e.target.value); setSearchItem(e.target.value); }; return ( <> <div className="searchbar"> <form onSubmit={(e) => e.preventDefault()}> <input name="name" placeholder="Enter Name, Email or Username to Search" type="text" className="search" value={searchItem} onChange={handleChange} /> </form> </div> <UserList searchItem={searchItem} /> </> ); };
For the uncontrolled approach the filter idea can stay untouched, but you remove the value
and onChange
props on the input
and use your handleSubmit
function to set the searchItem
. To get the value of an input you need to use a ref using this approach. See this for more information.