Jak najlepiej obsłużyć filtrowanie danych po stronie frontendu jeśli "strzelamy" do api

0

Jak najlepiej obsłużyć filtrowanie danych po stronie frontendu jeśli "strzelamy" do api? Np. chce przefiltrować produkty po ich nazwie. Jak to zrobić aby przy wpisywaniu każdej litery nie szedł natychmiastowo strzał do api? Zakładam, że najlepiej zrobić to tak aby dopiero po tym jak przez 1 sek użytkownik nic nie wpisze to szedł strzał do api? Czy jest na to jakiś lepszy sposób? Jak to zaimplementować w react? Co wykorzystac?

0

Kiedyś uczyłem się Vue i był tam fragment, który wspominał o zrobieniu opóźnienia przy wpisywaniu do textarea. Dam tobie fragment kodu może pomoże Tobie:

Plik debounce.js

export default {
    data() {
        return {
            timeout: "",
        }
    },

    methods: {
        debounce(func, wait = 1000) {
            clearTimeout(this.timeout);
            this.timeout = setTimeout(func, wait);
        },
    },
};

Teraz w twoim komponencie gdzie masz input:

 update(e) {
      const task = () => (this.text = e.target.value);
      this.debounce(task, 500);
    },
  }

Funkcję task możesz przerobić tak żeby robiła zapytania do API.

0

Po wpisaniu pierwszej litery druga litera nie zmieni wyniku, tylko go zawęzi. Zatem robisz tylko jeden strzał do api a później tylko filtrujesz po stronie frontu. Trzeba tylko napisać kod, który sprawdza czy pierwsza litera się nie zmieniła i robi strzał tylko w przypadku zmiany tej litery.

Jeżeli wyników jest bardzo dużo, oczekuj od użytkownika większej ilości liter niż jedna.

0

@Haskell: To raczej nie ma sensu. Jak mam 100k danych do przefiltrowania to nie będę pobieral na raz wszystkich danych żeby potem je przefiltrować na froncie.

0

Dlatego napisałem, że w przypadki dużej ilości danych strzał do api robisz po wpisaniu kilku liter i nie pobierasz wszystkich danych tylko te, które zaczynają się od wpisanych przez użytkownika.

Czyli przykładowo użytkownik wpisuje 'alf' robisz strzał i pobierasz wszystkie słowa na 'alf', których już nie będzie 100k tylko pewnie kilkadziesiąt. Jeżeli użytkownik będzie dalej kontynuował słowo np. 'alfa' to już nie robisz strzału do api, tylko filtrujesz na froncie.

Pamiętaj, że użytkownik ma normalny komputer z kilka giga ramu i możesz część kosztownych operacji wykonywać po jego stronie po to żeby nie zarzynać serwera z api.

0

A co jeśli chciałbym za każdym razem wysyłać requesta do api przy filtrowaniu. Jak to najlepiej zrobić?

1
sajek587 napisał(a):

A co jeśli chciałbym za każdym razem wysyłać requesta do api przy filtrowaniu. Jak to najlepiej zrobić?

Robisz asynchronicznego fetcha, który po pobraniu danych aktualizuje stan. Poniżej przykład, pisany z łapy, więc mogą być jakieś proste błędy.

const Przyklad = () => {
  const [state, setState] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch('https://api');
      json_response = await response.json();
      setState(json_response);
    }

    fetchData();
  }, []);

  render(
    <div>
      {state.map(item => <div key={item}>{item}</div>)}
    </div>
  )
}

P.S. jeżeli chcesz to podpiąć pod inputa, to usuń useEffect i zostaw funkcję fetchData, którą podajesz do onChange inputa. W takim wypadku oczywiście trzeba jeszcze przekazać event z inputa i z niego odczytać value inputa.

const [state, setState] = useState([]);
cons [inputValue, setInputValue] = useState("");

const changeValue = event => {
  const value = event.target.value;
  setInputValue(value);
  fetchData(value);
}
const fetchData = async value => {
  const response = await fetch(`https://api/{value}`);
  json_response = await response.json();
  setState(json_response);
}

render(
  <div>
    <input name="name" id="name" onChange={changeValue} value={inputValue}/>
    {state.map(item => <div key={item}>{item}</div>)}
  </div>
)
0
Haskell napisał(a):
sajek587 napisał(a):

A co jeśli chciałbym za każdym razem wysyłać requesta do api przy filtrowaniu. Jak to najlepiej zrobić?

Robisz asynchronicznego fetcha, który po pobraniu danych aktualizuje stan. Poniżej przykład, pisany z łapy, więc mogą być jakieś proste błędy.

const Przyklad = () => {
  const [state, setState] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch('https://api');
      json_response = await response.json();
      setState(json_response);
    }

    fetchData();
  }, []);

  render(
    <div>
      {state.map(item => <div key={item}>{item}</div>)}
    </div>
  )
}

P.S. jeżeli chcesz to podpiąć pod inputa, to usuń useEffect i zostaw funkcję fetchData, którą podajesz do onChange inputa. W takim wypadku oczywiście trzeba jeszcze przekazać event z inputa i z niego odczytać value inputa.

const [state, setState] = useState([]);
cons [inputValue, setInputValue] = useState("");

const changeValue = event => {
  const value = event.target.value;
  setInputValue(value);
  fetchData(value);
}
const fetchData = async value => {
  const response = await fetch(`https://api/{value}`);
  json_response = await response.json();
  setState(json_response);
}

render(
  <div>
    <input name="name" id="name" onChange={changeValue} value={inputValue}/>
    {state.map(item => <div key={item}>{item}</div>)}
  </div>
)

Tylko czy w tym przypadku mogło by iść za dużo requestów do api? Nie powinno być jakiegoś debounce timea?

1 użytkowników online, w tym zalogowanych: 0, gości: 1