Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

This text input goes unchecked every time I press a key. In order to continue typing I have to click it again. Why?

The textInput component goes unchecked on every key I press, making it completely useless. I tried with useMemo, with a custom component. Nothing. This still doesn’t work.


import React, { useState, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { Link } from 'react-router-dom';
import { setPageTitle } from '../store/themeConfigSlice';
import { getCustomers } from '../services/customerService';
import { DataTable, ActionIcon, TextInput } from 'mantine-datatable';
import { IconSearch, IconX } from '@tabler/icons-react';

const Customers = (): any => {
  const dispatch = useDispatch();

  const [customers, setCustomers] = useState([] as any);
  const [customersNotEmpty, setCustomersNotEmpty] = useState(false as boolean);

  useEffect(() => {
    dispatch(setPageTitle('Customers'));
  }, []);

  useEffect(() => {
    getCustomers()
      .then((response) => setCustomers(response.data))
      .then(() => setCustomersNotEmpty(true));
  }, [customersNotEmpty]);

  const [filter, setFilter] = useState('');

  const filteredData = customers?.filter((item: any) =>
    item.name.toLowerCase().includes(filter.toLowerCase())
  );

  const NameColumnHeader = () => (
    <div className="flex items-center justify-between">
      <span className="mr-2">Name</span>
      <TextInput
        className=""
        label=""
        placeholder="Search by Name..."
        value={filter}
        onChange={(e) => setFilter(e.currentTarget.value)}
        rightSection={
          filter && (
            <ActionIcon
              size="sm"
              variant="transparent"
              c="dimmed"
              onClick={() => setFilter('')}
            >
              <IconX size={14} />
            </ActionIcon>
          )
        }
      />
    </div>
  );

  return (
    <div>
      <ul className="flex space-x-2 rtl:space-x-reverse">
        <li>
          <Link to="/" className="text-primary hover:underline">
            Dashboard
          </Link>
        </li>
        <li className="before:content-['/'] ltr:before:mr-2 rtl:before:ml-2">
          <span>Customers</span>
        </li>
      </ul>
      <div className="flex flex-col xl:flex-row gap-5 relative mt-5">
        <DataTable
          noRecordsText="No results match your search query"
          highlightOnHover
          className="whitespace-nowrap table-hover"
          records={filteredData}
          columns={[
            { accessor: 'client_id', title: '#' },
            { accessor: 'name', title: <NameColumnHeader /> },
            { accessor: 'code', title: 'Code' },
            { accessor: 'address_city', title: 'City' },
            { accessor: 'address_province', title: 'Province' },
            { accessor: 'country', title: 'Country' },
            { accessor: 'vat_number', title: 'VAT' },
            { accessor: 'id', title: 'ID' },
          ]}
          totalRecords={customers?.length}
          recordsPerPage={10}
          page={1}
          onPageChange={() => null}
          recordsPerPageOptions={[0]}
          onRecordsPerPageChange={() => null}
          sortStatus={undefined}
          onSortStatusChange={undefined}
          minHeight={200}
          paginationText={({ from, to, totalRecords }) =>
            `Showing  ${from} to ${to} of ${totalRecords} entries`
          }
        />
      </div>
    </div>
  );
};

export default Customers;

I don’t know what to do. Both TextInput and DataTable components are from Mantine.
How can I get a simple, working, table with filtering?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Your code above defines NameColumnHeader inside a component named Customers.

A component is a JavaScript function. When a component "renders", you are simply running that JavaScript function.

You have defined a function (let’s call it B()) inside of a function (A()). Every single time that A() is run, it will recreate B(). It is not the same B() as in the previous run.

In React terms: you have defined a component <B> inside of the code of component <A>. Each time that <A> renders, you get a new component called <B>.

Do not define components inside of components. 99.47% of the time you will not be happy with the results.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading