Home > Blockchain >  How to display "no records found" after running a search in React
How to display "no records found" after running a search in React

Time:10-19

I have been trying to add "no records found" message after running a search for worker names. But I have not been successful. I either get 20 "no records found" messages or none at all. I am not sure what I am doing wrong, but I have been trying for last 4 hours various methods and work arounds.

I know that this should be simple to implement, but it has been difficult. Here is a link to my code on codesandbox: https://codesandbox.io/s/fe-hatc-ass-search-n62kw?file=/src/App.js

Any insights would be helpful.... Things I tried were, if else statements, logical operators... etc...

CodePudding user response:

Looking at your code, the problem is because you're doing the filtering in each individual <Order> component. The filtering should be done in the parent Orders component and you should only render an <Order> component if a match is found.

Currently, your <Order> component is rendering, even if there's no match.

CodePudding user response:

You could add an state in the Orders.js to count how many items are being presented. However, since each Worker depends on an api call, you would need to have the response (getWorker, in Workers.js) wait for the response in order to make the count. Every time the input value changes, you should reset the counter to 0.

https://codesandbox.io/s/fe-hatc-ass-search-forked-elyjz?file=/src/Worker.js:267-276

Also, as a comment, it is safer to put the functions that are run in useEffect, inside the useEffect, this way it is easier to see if you are missing a dependency.

CodePudding user response:

In my opinion the first thing you need to think about is what data do you need and when do you need it. To display no results like you want you are going to need the workers name in the component that is doing the filtering. So you would need it in the orders component. I would merge the worker data with the order data and then you can just filter and manipulate the data after that. That would also stop you from making an api request every time someone changes the input and all you need to do is filter the already fetched data. Then you can check the array length and if it is greater than 0 you can display results else display a no results statement.

So something like the following:

Orders component

import React, { useEffect, useState } from "react";
import "./Orders.css";
import Order from "./Worker";
import axios from "axios";

const Orders = () => {
  const [orders, setOrders] = useState([]);
  const [results, setResults] = useState([]);
  const [searchedWorker, setSearchedWorker] = useState("");

  const getOrders = async () => {
    const workOrders = await axios.get(
      "https://api.hatchways.io/assessment/work_orders"
    );
    const mappedOrders = await Promise.all(workOrders.data.orders.map(async order => {
      const worker = await axios.get(
        `https://api.hatchways.io/assessment/workers/${order.workerId}`
      );
      return {...order, worker: worker.data.worker}
    }))
    setOrders(mappedOrders);
  };

  useEffect(() => {
    getOrders();
  }, []);

  useEffect(() => {
    const filtered = orders.filter(order => order.worker.name.toLowerCase().includes(searchedWorker));
    setResults(filtered)
  }, [searchedWorker, orders])

  return (
    <div>
      <h1>Orders</h1>
      <input
        type="text"
        name="workerName"
        id="workerName"
        placeholder="Filter by workername..."
        value={searchedWorker} //property specifies the value associated with the input
        onChange={(e) => setSearchedWorker(e.target.value.toLowerCase())}
        //onChange captures the entered values and stores it inside our state hooks
        //then we pass the searched values as props into the component
      />

      <p>Results: {results.length}</p>

      {results.length > 0 ? results.map((order) => (
        <Order key={order.id} lemon={order} />
      )) : <p>No results found</p> }
    </div>
  );
};
//(if this part is true) && (this part will execute)
//is short for: if(condition){(this part will execute)}
export default Orders;

Then you can simplify your single order component

import React from "react";

const Order = ({ lemon }) => {
  return (
    <div>
      <div className="order">
        <p>Work order {lemon.id}</p>
        <p>{lemon.description}</p>
        <img src={`${lemon.worker.image}`} alt="worker" />
        <p>{lemon.worker.name}</p>
        <p>{lemon.worker.company}</p>
        <p>{lemon.worker.email}</p>
        <p>{new Date(lemon.deadline).toLocaleString()}</p>
      </div>
    </

div>
  );
};

export default Order;
  • Related