Skip to content
Advertisement

Using react-router to redirect upon form submission

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.

enter image description here

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.

sandbox example

Advertisement