Wątek przeniesiony 2022-09-28 11:36 z Webmastering przez Riddle.

Prawidłowa metoda usuwania wiersza?

0

Cześć.

Mam problem natury metodologicznej, chociaż moja implementacja dotyczy akurat React (ze stroną techniczną nie mam większych problemów - większość jest już zaimplementowana, chociaż nie wiem czy poprawnie).
fragment app.jpg

Po lewej stronie GUI mam zaimplementowany komponent RowTripFormLeft, a po prawej RowWorkOffFormRight.

{/* fragment aplikacji RowTripFormLeft */}
<div className="w-50 float-start">
  {this.state.workOffs?.map((url_work_off) => (
      <RowWorkOffFormRight 
          key={url_work_off} 
          url_work_off={url_work_off} 
          getRemoveWorkOff={this.getRemoveWorkOff}
          passMinutes={this.getWorkOffMinutes}
          isLoading ={this.workOffLoading}
                  > 
          </RowWorkOffFormRight>
  ))}
      <Button className="ms-5" name="add_work_off" onClick={this.add_work_off}>Dodaj czas odpracowania</Button>
</div>

Mam pytanie o prawidłowy wybór metodologii działania getRemoveWorkOff:

  1. Usuwanie bezpośrednie wiersza.
    1.1. appka wywołuje fetch na API do usunięcia wiersza z tabeli WorkOff bazy danych
    1.2. appka czeka na zwrotną informację o sukcesie i wtedy usuwamy wiersz (nadpisujemy stan workOffs po reduce + wywołujemy ponownie bilans odpracowywania)
  2. Usuwanie z bazy i zaciąganie z bazy wszystkich workoff.
    2.1. appka wywołuje fetch na API do usunięcia z bazy danych wiersza workoff
    2.2. appka wywołuje fetch stanu workOffs dla danego wiersza po lewej stronie (trip)

Domyślam się, że podejście 1. jest bardziej w filozofii SPA ale ma dużą wadę: dużo więcej kroków/kodu => większe szanse na pomyłki w kodzie.

Z góry dziękuję za każdą odpowiedź i radę.

PS. korzystam też z Symfony + API Platform

3

Dla Reacta to chyba bez znaczenia, bo komponenty są rerenderowane przy zmianie key. Więc nawet jak fetchujesz wszystko, to w wirtualnym DOMie on to porównuje i rerenderuje tylko to, co trzeba, więc w tym przypadku wyrzuca usunięty element.

Ale w Reakcie nie pisałem, więc mogę bredzić XD

2

Z punktu widzenia Reacta nie ma znaczenia, czy nadpiszesz stan przez reduce, czy pobierzesz nowy z API, bo on i tak zaktualizuje DOM w taki sam sposób (zaczeka na zmianę stanu w komponencie i usunie elementy z nieaktualnym atrybutem key), więc wybierz rozwiązanie, które jest prostsze według Ciebie.

1

Dzięki za odpowiedzi. Przy metodzie 1 miałem problemy ze zliczaniem odpracowywań.

Kod metody remove_work_off (w komponencie RowWorkOffFormRight).

    remove_work_off = (e) => {
        this.props.isLoading(this.props.url_work_off,true);
        deleteWorkOff(this.props.url_work_off)
         .then((e) =>{
             this.props.getRemoveWorkOffUrl(this.props.url_work_off);
             this.props.isLoading(this.props.url_work_off,false);
        });
    }

Kod Metody this.getRemoveWorkOff (w komponencie RowTripFormLeft).

    getRemoveWorkOffUrl = (work_off_url) => {
         this.setState({ 
             workOffs: this.state.workOffs.filter((el) => el !== work_off_url)
         })
// tutaj miałem kod który mnie wkurzał (obliczanie odpracowywań):
         let work_off_minutes_temp = this.state.work_off_minutes;
       delete work_off_minutes_temp[work_off_url];

       this.setState({work_off_minutes: work_off_minutes_temp}, () => {
            this.setState({
                 sum_work_off_minutes : Object.values(this.state.work_off_minutes).reduce((partialSum, a) => partialSum + a)
             });
     }

Mam nadzieję że dobrze zrozumiałem zagadnienie i da się zrobić tak jak w punkcie 2,
pozdrawiam

1
pomuk napisał(a):

Kod Metody this.getRemoveWorkOff (w komponencie RowTripFormLeft).

    getRemoveWorkOffUrl = (work_off_url) => {
         this.setState({ 
             workOffs: this.state.workOffs.filter((el) => el !== work_off_url)
         })
// tutaj miałem kod który mnie wkurzał (obliczanie odpracowywań):
         let work_off_minutes_temp = this.state.work_off_minutes;
       delete work_off_minutes_temp[work_off_url];

       this.setState({work_off_minutes: work_off_minutes_temp}, () => {
            this.setState({
                 sum_work_off_minutes : Object.values(this.state.work_off_minutes).reduce((partialSum, a) => partialSum + a)
             });
     }

Twoja wersja powinna działać, ale nie wiem, czy wiesz, że przez setState można zaktualizować więcej niż jedną wartość tylko musisz sprawdzić, czy nie ma żadnego błędu logicznego :P

getRemoveWorkOffUrl = (work_off_url) => {
  const work_off_minutes_temp = this.state.work_off_minutes;
  delete work_off_minutes_temp[work_off_url];

  this.setState({
    work_off_minutes: work_off_minutes_temp,
    workOffs: this.state.workOffs.filter((el) => el !== work_off_url),
    sum_work_off_minutes: Object.values(work_off_minutes_temp).reduce((partialSum, a) => partialSum + a)
  });
}
0

Dzięki, bardzo pomocne.
Wczoraj robiłem drobne refaktoryzacje - mój kod staje się dosyć rozległy i miejscami nieczytelny. Każda rada refaktoryzacyjna mile widziana.

1
pomuk napisał(a):

Dzięki, bardzo pomocne.
Wczoraj robiłem drobne refaktoryzacje - mój kod staje się dosyć rozległy i miejscami nieczytelny. Każda rada refaktoryzacyjna mile widziana.

W takim razie jeszcze można przerobić funkcję remove_work_off na zapis async / await. W działaniu nic się nie zmieni , jedynie zmiana czysto kosmetyczna.

remove_work_off = async (e) => {
  const { url_work_off, isLoading, getRemoveWorkOffUrl } = this.props;

  isLoading(this.props., true);

  await this.deleteWorkOff(this.props.url_work_off);
  
  getRemoveWorkOffUrl(url_work_off);
  isLoading(url_work_off, false);
}

Podobnie jak destrukturyzacja wartości z this.props / this.state i zamiast pisać this.props.getRemoveWorkOffUrl, this.state.work_off_minutes to w niektórych przypadkach można to skrócić w taki sposób (szczególnie ma to sens w metodach, gdzie korzystasz kilka razy z danej właściwości)

const { getRemoveWorkOffUrl } = this.props;
const { work_off_minutes } = this.state;

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