Home > Software design >  Filtering data and returning it next to the "permanent" data - react
Filtering data and returning it next to the "permanent" data - react

Time:10-16

I added a TextField from the MUI library, and used a useRef hook to capture the value "live" as the user types something. The intention is to filter only the rates which include the characters he types. As of right now:

Object.keys(rates["rates"]) // ["EUR", "RON", "CZK", ...]

I added a form, and I want it to stay persistent, but the buttons should change dynamically. If the user has not typed anything I want to return everything (like nothing is filtered)

My try:

import React, {useEffect, useRef, useState} from 'react'
import Button from '@mui/material/Button';
import CircularProgress from '@mui/material/CircularProgress';
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';

const RatesButton = () => {
    const rateRef = useRef('')
    const [rates, setRates] = useState([]);
    useEffect(
        () => {
            fetch("https://api.vatcomply.com/rates")
                .then(ratesResponse => ratesResponse.json())
                .then(rates => setRates(rates));
        }
        , [])


    if (rates.length === 0) {
        return (
            <Box sx={{display: 'flex', justifyContent: 'center'}}>
                <CircularProgress/>
            </Box>
        )
    }

    const rateSearch = () => {
        Object.keys(rates["rates"]).filter(
            rate => rate.includes(rateRef.current.value)
        ).map(rate => {

                return (
                    <Button>
                        {rate}
                    </Button>
                )
            }
        )

    }

    return (
        <>
            <br/>
            <TextField id="rate-search" onChange={rateSearch} inputRef={rateRef} label="Rate" variant="outlined"/>
        </>
    )
}


export default RatesButton

It works nicely I think, I can access the reference of the input of the user, filter all the rates that contain the letters, and map each one to a MUI Button. The problem is that they don't show somehow, and I am pretty lost, it is pretty confusing how I can return from two different functions at the same time, while keeping one persistent (the input field)

Picture of the input

The buttons do not show unfortunately...

CodePudding user response:

You should use Codesandbox Demo

CodePudding user response:

    import React, {useState} from 'react';
    import { throttle } from 'lodash';

    const RatesButton = () => {
      const [value, setValue] = useState("");
      const [rates, setRates] = useState({});

      useEffect(() => {
        fetch("https://api.vatcomply.com/rates")
          .then((ratesResponse) => ratesResponse.json())
          .then((rates) => setRates(rates.rates ?? {}));
      }, []);
      
      const handleChange = (e) => setValue(e.target.value);
      
      // it will prevent multiple render during fast typing
      const throttledChange = throttle(handleChange, 400);

      return (
        <>
          {Object.keys(rates).length === 0 && (
            <Box sx={{ display: "flex", justifyContent: "center" }}>
              <CircularProgress />
            </Box>
          )}
          {Object.keys(rates)
            .filter((rate) => rate.toLowerCase().includes(value.toLowerCase()))
            .map((rate) => {
              return <Button>{rate}</Button>;
            })}
          <br />
          <TextField
            id="rate-search"
            onChange={throttledChange} // don't use arrow function
            label="Rate"
            variant="outlined"
          />
        </>
      );
    };
  • Related