score:3

Accepted answer

i fixed pagination with filter with the help of usememo hook. the problem was that i was filtering the default array and i wasn't updating the totaltodos with the length of computed todos etc.. now inside usememo hook, i compute(filter) the todos first and then i update totaltodos with the length of computed todos.

import { usestate, useeffect, usememo } from "react";
import axios from "axios";
import "./styles.css";

export default function app() {
  const [todos, settodos] = usestate([]);
  const [searchterm, setsearchterm] = usestate("");
  const [filtercompleted, setfiltercompleted] = usestate("");

  const [currentpage, setcurrentpage] = usestate(1);
  const [totaltodos, settotaltodos] = usestate(0);
  const todosperpage = 10;

  useeffect(() => {
    axios
      .get(`https://jsonplaceholder.typicode.com/todos`)
      .then((response) => {
        settodos(response.data);
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  
  const pagenumbers = [];

  for (let i = 1; i <= math.ceil(totaltodos / todosperpage); i++) {
    pagenumbers.push(i);
  }


  const todosdata = usememo(() => {
    let computedtodos = todos;

    if (searchterm) {
        computedtodos = computedtodos.filter(
            todo =>
            todo.title.tolowercase().includes(searchterm.tolowercase())
        );
    }

    if (filtercompleted === "true") {
      computedtodos = computedtodos.filter(
          todo =>
          filtercompleted === "true" && todo.completed === true
      )
  }

  if (filtercompleted === "false") {
    computedtodos = computedtodos.filter(
        todo =>
        filtercompleted === "false" && todo.completed === false
    )
  }

    settotaltodos(computedtodos.length);

    //current page slice
    return computedtodos.slice(
        (currentpage - 1) * todosperpage,
        (currentpage - 1) * todosperpage + todosperpage
    );
}, [todos, currentpage, searchterm, filtercompleted]);
  // change page
  const paginate = (pagenumber) => setcurrentpage(pagenumber);

  const resetfilter = () => {
    setsearchterm("");
    setfiltercompleted("");
    setcurrentpage(1);
  };

  return (
    <div classname="container">
      <h3>filters</h3>
      <div classname="mb-3">
        <label htmlfor="search" classname="form-label">
          search
        </label>
        <input
          type="text"
          classname="form-control"
          id="search"
          placeholder="search title"
          value={searchterm}
          onchange={(e) => {
            setsearchterm(e.target.value);
            setcurrentpage(1);
          }}
        />
      </div>
      <div classname="mb-3">
        <label htmlfor="search" classname="form-label">
          completed
        </label>
        <select
          classname="form-select"
          value={filtercompleted}
          onchange={(e) => {
            setfiltercompleted(e.target.value);
            setcurrentpage(1);
          }}
        >
          <option defaultvalue=""></option>
          <option value="true">true</option>
          <option value="false">false</option>
        </select>
      </div>
      <div classname="mb-3">
        <button
          type="button"
          classname="btn btn-danger btn-sm"
          onclick={resetfilter}
        >
          reset filters
        </button>
      </div>

      <nav>
        <ul classname="pagination">
          {pagenumbers.map((number) => (
            <li key={number} classname="page-item">
              <button onclick={() => paginate(number)} classname="page-link">
                {number}
              </button>
            </li>
          ))}
        </ul>
      </nav>

      {todosdata
        .map((todo) => {
          return (
            <div key={todo.id} classname="card margin-bottom">
              <h5 classname="card-header">
                <div classname="card-header-flex">
                  <span classname="id">{`#${todo.id}`}</span>
                </div>
              </h5>
              <div classname="card-body">
                <div classname="card-text">
                  <div classname="card-body-flex">
                    <span>{`title: ${todo.title}`}</span>
                    <span>{`completed: ${todo.completed}`}</span>
                  </div>
                </div>
              </div>
            </div>
          );
        })}
    </div>
  );
}

Related Query

More Query from same tag