How can I filter the rows’ table while typing in the searchbar using react since the beginning?

I have two components in the App file, the Header and the Table.
Based on the styleNumber, I have to filter the rows that match those styleNumber using the API endpoint.
In the Header, I have a searchbar, so when I type I can filter and get the rows with that styleNumber. So, I’m passing the styleNumber to both components and the state is in App.
My issue is that I have to type the entire styleNumber to do the rows’ table filtering.
Instead I’d like to start doing the filtering when I start typing and at the same time, the table has to show , on every input, the rows that have those numbers. It’s like a dynamic filtering as all the searchbar do, right?
How can I fix this issue?
This is my header component:

interface HeaderProps {
  styleNumber: string;
  setStyleNumber: React.Dispatch<React.SetStateAction<string>>;
}

export const Header = ({ styleNumber, setStyleNumber }: HeaderProps): ReactElement => {

  const [inputValue, setInputValue] = useState<string>('');
  const { login } = useContext(AuthorizationContext);
  const [hasFocus, setHasFocus] = useState<boolean>(false);
  const inputRef = useRef<ElementRef<'input'>>(null);
  const { palette } = useTheme();
  const theme = useTheme();
  const { instance, accounts } = useMsal();
  const isAuthenticated = useIsAuthenticated();
  const account = useAccount(accounts[0] || {});
  const [openDialog, setOpenDialog] = useState(false);
  const [openCreateCertificateDialog, setOpenCreateCertificateDialog] = useState(false);

  const iconSize = 24;
  const boxHeightSearchBar = 56;
  const fontFamilySeachBar = 18;

  // I fetch the style number in the API
const fetchCertificatesByStyleNumber = async (
  // eslint-disable-next-line @typescript-eslint/no-shadow
  styleNumber: string,
  // eslint-disable-next-line @typescript-eslint/no-shadow
  setStyleNumber: React.Dispatch<React.SetStateAction<string>>
): Promise<void> => {
  try {
    // Convert styleNumber to a number
    const numericStyleNumber = parseInt(styleNumber, 10);

    // Check if it's a valid number before making the request
    if (!isNaN(numericStyleNumber)) {
      const response = await axios.get(
        `https://hello.com/safety-certificate/certificate/certificate/${numericStyleNumber}`
      );

      const certificates = response.data.certificates;
      // eslint-disable-next-line no-console
      console.log('API Response:', response);

      // Update the parent component's styleNumber state
      setStyleNumber(styleNumber);
    } else {
      console.error('Invalid styleNumber:', styleNumber);
    }
  } catch (error) {
    console.error('Error fetching certificates:', error);
  }
};

  // this manages the input value
const handleInputChange = async (event: ChangeEvent<HTMLInputElement>): Promise<void> => {
  const value = event.target.value;
  setInputValue(value);

  // Assuming I want to fetch certificates when the input changes
  await fetchCertificatesByStyleNumber(value, setStyleNumber);
};
  // eslint-disable-next-line no-console
  console.log(inputValue);
  // // Function to clear the input
  const handleClearInput = (): void => {
    setInputValue('');
  };

const handleShowDialog = (): void => {
    setOpenDialog(true);
  };

const handleCloseDialog = (): void => {
    setOpenDialog(false);
  };

  const handleOnSignIn = (): void =>{
    login();
  };

  const handleSignOut = (): void => {
    instance.logoutRedirect({
      account,
    }).then(() => {
    })
.catch((error) => {
      // Handle logout error if needed
      console.error('Logout error:', error);
    });
  };

  const handleCreateCertificate = (): void => {
    setOpenCreateCertificateDialog(true);
  };

  return (
    <Box
      sx={{
        paddingLeft: 10,
        paddingRight: 10,
        paddingTop: 10,
        paddingBottom: 3,
        display: 'flex',
        flexDirection: 'row',
        alignItems: 'center',
      }}
    >
      <Box
        alignItems='center'
        justifyContent='center'
        display='flex'
        sx={{
          marginRight: '20px',
        }}
      >
        <Typography variant="h1">BESTSELLER</Typography>
      </Box>
      <Box sx={{ flex: '5', display: 'flex', justifyContent: 'center', marginLeft: '12px' }}>
        <TextField
          variant="outlined"
          placeholder='Search by style number'
          value={inputValue}
          sx={{
            ['& .MuiInputBase-root']: {
              height: boxHeightSearchBar,
            },
            ['& .MuiOutlinedInput-root']: {
              mt: '0 !important',
              pr: inputValue ? 2 : !hasFocus ? 5 : 0,
            },
            ['& .MuiOutlinedInput-input']: {
              fontSize: fontFamilySeachBar,
            },
          }}
          InputProps={{
            inputProps: {
              id: innerInputId,
              ref: inputRef,
            },
            startAdornment: (
              <InputAdornment position="start" sx={{ mr: 0 }}>
                <SearchIcon color={palette.text.primary} style={{ width: iconSize, height: iconSize }} />
              </InputAdornment>
            ),
            endAdornment: (
              <InputAdornment position="end">
                {inputValue && (
                  <IconButton onClick={handleClearInput}>
                    <CrossIcon
                      style={{ width: iconSize, height: iconSize }}
                    />
                  </IconButton>
                )}
              </InputAdornment>
            ),
          }}
          fullWidth
          // eslint-disable-next-line @typescript-eslint/no-misused-promises
          **onChange={handleInputChange}**
          onFocus={(): void => void setHasFocus(true)}
          onBlur={(): void => void setHasFocus(false)}
        />
      </Box>

My table component:

export interface CertificateData {
  certificateNumber: string;
  brandNumber: string;
  styleNumber: number;
  ceDocumentName: string;
  ceDocumentUrl: string;
  createdBy: string;
  changedBy: string;
  isDeleted: boolean;
  createdDate: string;
}

export interface BrandData {
  brandName: string;
  brandNumber: string;
  isDeleted: boolean;
}

interface FilteredTable {
  styleNumber: string;
}

export const TableComponent = ({ styleNumber }: FilteredTable) => {
  const [certificates, setCertificates] = useState<Array<CertificateData>>([]);
  const [brands, setBrands] = useState<Array<BrandData>>([]);
  const [page, setPage] = useState(0);
  const [rowsPerPage, setRowsPerPage] = useState(5);
  const isAuthenticated = useIsAuthenticated();
  const [isDialogOpen, setDialogOpen] = useState(false);
  const [selectedCertificate, setSelectedCertificate] = useState<CertificateData | null>(null);

  useEffect(() => {
    // Fetch certificates
    axios
      .get('https://hello.com/safety-certificate/certificate/certificates')
      .then((response) => {
        console.log('Certificates Response:', response.data);
        setCertificates(response.data.certificates);
      })
      .catch((error) => {
        console.error('Certificates Error:', error);
      });

    // Fetch brands
    axios
      .get('https://hello.com/safety-certificate/brand/brands')
      .then((response) => {
        console.log('Brands Response:', response.data);
        setBrands(response.data.brands);
      })
      .catch((error) => {
        console.error('Brands Error:', error);
      });
  }, []);

  const handleChangePage = (event: unknown, newPage: number) => {
    setPage(newPage);
  };

  const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
    setRowsPerPage(parseInt(event.target.value, 10));
    setPage(0);
  };


const handleEditIconClick = (event: React.MouseEvent<HTMLButtonElement>, certificate: CertificateData): void => {
  setSelectedCertificate(certificate);
  setDialogOpen(true);
};

// Convert styleNumber to a number
const numericStyleNumber = parseInt(styleNumber, 10);

// Filter certificates based on the numericStyleNumber
const filteredCertificates = !isNaN(numericStyleNumber)
  ? certificates.filter((certificate) => certificate.styleNumber === numericStyleNumber)
  : certificates;

return (
  <Box>
    <TableContainer component={Paper}>
      <Table sx={{ minWidth: 700 }} aria-label="safety-certificates table">
        <TableHead>
          <TableRow>
            <StyledTableCell align="right">Style Number</StyledTableCell>
            <StyledTableCell align="right">Brand Name</StyledTableCell>
            {isAuthenticated && <StyledTableCell align="right">Created By</StyledTableCell>}
            <StyledTableCell align="right">CE-document</StyledTableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {filteredCertificates.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((certificate) => (
            <StyledTableRow key={certificate.certificateNumber}>
              <StyledTableCell align="right">{certificate.styleNumber}</StyledTableCell>
              <StyledTableCell align="right">
                {brands.find((brand) => brand.brandNumber === certificate.brandNumber)?.brandName ?? 'Brand Not Found'}
              </StyledTableCell>
              {isAuthenticated && (
                <StyledTableCell align="right">{certificate.createdBy}</StyledTableCell>
            )}
              <StyledTableCell align="right">
                <Box>
                  <a
                    href={`https://buying-dev.bestseller.com/safety-certificate/certificate/certificatePdf/${certificate.certificateNumber}`}
                    target="_blank"
                    download={certificate.ceDocumentName}
                    rel="noreferrer"
                    style={{ color: 'black', textDecoration: 'none' }}
                  >
                    <span>{certificate.ceDocumentName}</span>
                  </a>
                  {isAuthenticated && (
                    <IconButton onClick={(event): void => void handleEditIconClick(event, certificate)}>
                      <EditIcon />
                    </IconButton>
                )}
                </Box>
              </StyledTableCell>
            </StyledTableRow>
        ))}
        </TableBody>
      </Table>
      <TablePagination
        rowsPerPageOptions={[5, 10, 25, 50]}
        component="div"
        count={certificates.length ?? 0}
        rowsPerPage={rowsPerPage}
        page={page}
        labelRowsPerPage="Documents per page"
        onPageChange={handleChangePage}
        onRowsPerPageChange={handleChangeRowsPerPage}
      />
    </TableContainer>

My app file:

const [styleNumber, setStyleNumber] = useState<string>('');

  return (
    <MsalProvider instance={msalService.msalInstance}>
      <AuthenticationProvider>
        <ThemeProvider theme={theme}>
          <Header styleNumber={styleNumber} setStyleNumber={setStyleNumber} />
          <TableComponent styleNumber={styleNumber} />
        </ThemeProvider>
      </AuthenticationProvider>
    </MsalProvider>

  );