Jak v Reactu ci Vue modifikovat jen jeden řádek vykreslené tabulky?

Mam tady takovy principielni dotaz ohledne typu probemu, na ktery jsem narazil.

Rekneme ze mam nejaky list zaznamu v globalnim state, je jich 5000, a jsou vykreslene do tabulky. A nechci z nejakeho duvodu pouzit pagination - predstavte si ze je to neco na zpusob tabulky v excelu.

Vsiml jsem si ve vue, ze kdyz u jednoho zaznamu zmenim hodnotu nejakeho fieldu, tak ze dojde k prekresleni vsech ostatnich 4999 zaznamu v tabulce. Coz je vlastne docela logicke, a je to kupodivu docela rychle - nicmene lepsi by bylo to udelat jinak.

Chapu to spravne, ze jediny zpusob reseni je vytvorit pro radky v tabulce separatni komponentu, pres props ji predat hodnoty, uvnitr v komponente si z tech props nastavit vnitrni state, a nasledne render radku udelat z toho vnitrniho state, takze kdyz dojde ke zmene nejakeho sloupce, tak se zmena nepropise do globalniho stavu? A pridat k tomu radku tlacitko Ulozit, na ktere az kdyz se klikne tak se to propise ze state do globalniho stavu?

Ma to jeste nejake jine reseni, jak aktualizovat globalni stav ze ktereho se dela foreach, ale zabranit opetovnemu provedeni foreach?
« Poslední změna: 14. 06. 2021, 09:29:37 od Petr Krčmář »


Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #1 kdy: 11. 06. 2021, 23:59:45 »
Vsiml jsem si ve vue, ze kdyz u jednoho zaznamu zmenim hodnotu nejakeho fieldu, tak ze dojde k prekresleni vsech ostatnich 4999 zaznamu v tabulce.

na to jste prisel jak? Jak Vue tak React delaji DOM diff komponenty a prekresluji jen zmenene nody.

Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #2 kdy: 12. 06. 2021, 00:09:18 »
Vsiml jsem si ve vue, ze kdyz u jednoho zaznamu zmenim hodnotu nejakeho fieldu, tak ze dojde k prekresleni vsech ostatnich 4999 zaznamu v tabulce.

na to jste prisel jak? Jak Vue tak React delaji DOM diff komponenty a prekresluji jen zmenene nody.

Testoval jsem to tak, ze jsem si udelal metodu called(), dal ji do kazdeho radku, a ta vypise do konzole zaznam. Nasledne kdyz modifikuju "foodEntry.amount", tak dojde k zavolani metody called()  na vsech vykreslenych radcich. Takze kdyby jich bylo 1000, tak called() se zavola 1000x.

Kód: [Vybrat]

    <!--   Header   -->

    <table class="table-sm">
      <thead>
      <tr>
        <th class="table-date">Datum</th>
        <th class="table-food">Potravina</th>
        <th class="table-amount">Mnozstvi</th>
        <th class="table-calories">Energie</th>
        <th class="table-buttons"></th>
        <th class="table-buttons"></th>
      </tr>
      </thead>
      <tbody>

      <template v-for="(foodEntries, date) in this.$root.$data.foodEntriesByDate">
        <tr :key="date">
          <td>
            {{ date }} {{called()}}
          </td>
        </tr>

        <template v-if="date > '2021-06-10'" >
          <tr v-for="foodEntry in foodEntries" :key="foodEntry.id">
            <td>{{called()}}</td>
            <td>{{ foodEntry.food.name }}</td>
            <td><input class="form-control form-control-sm" type="number" step="20" v-model="foodEntry.amount"/></td>
            <td>{{ foodEntry.getTotalCalories() }}</td>
            <td>
            </td>
          </tr>
        </template>

      </template>

Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #3 kdy: 12. 06. 2021, 00:29:46 »
To prokazuje jen, ze se vygeneruje virtualni DOM, ne ze se to cele prekresli.

L..

  • ****
  • 302
    • Zobrazit profil
    • E-mail
Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #4 kdy: 12. 06. 2021, 06:57:03 »
Radit ti je zbytečné, protože stejně všechny rady ignoruješ, ale kdyby to zajímalo někoho jiného:

Nevím jak ve Vue, v Reactu se to řešit dá. Například tak, že si člověk dá do Reduxu jednak objekt (asociativní pole) s obsahem klíč => řádek a pak pole klíčů, které určuje pořadí řádků. Pro každý řádek je komponenta a jako property má klíč řádku, který zobrazuje. Je napojená na Redux a z něj si z mapy příslušný řádek vyzvedne.

Když se změní řádek, tak pole klíčů se nemění, takže "for each" neproběhne. Změní se pouze asociativní pole. Proběhnou selektory pro každý řádek, ale až na jeden vrátí ten samý objekt, takže se vyvolá render pouze pro ten jeden změněný řádek.

Jinak co se týče řešení s kopií dat a tlačítkem "uložit", to je taky možnost.


Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #5 kdy: 12. 06. 2021, 09:27:35 »
Jak píšou ostatní, snad to nejdůležitější, co dělají React i Vue (a další) „pod kapotou“, je to, že zjišťují, co se doopravdy změnilo, aby v DOMu prohlížeče změnili opravdu jen to, co je potřeba změnit. Proto po vás React chce přidávat atribut key a Vue bindování :key, když vypisujete seznam, protože bez toho nedokážou zjistit, co přesně se v seznamu změnilo.

Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #6 kdy: 12. 06. 2021, 10:36:37 »
Kdyz udelam ve Vue toto:

Kód: [Vybrat]

      <template v-for="idx in 10">
          <div :key="idx">{{$root.$data.foodEntries[idx].amount}} {{called()}} </div>
      </template>


A potom:

Kód: [Vybrat]
  mounted() {
    setInterval( () => {
      console.log(this.$root.$data.foodEntries[1].amount++);
    },1000);
  }

Tak vysup z logu:

Kód: [Vybrat]
Menu.vue?ae1e:172 386
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:169 387
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:172 389
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:86 Called!
Menu.vue?ae1e:169 390

Tzn. modifikace fieldu zpusobi prinejmensim zavolani vsech metod ve foreach.

Zatim se mi jako jedine vychodisko jevi resit to pres vnitrni stav komponenty.


Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #7 kdy: 12. 06. 2021, 11:06:08 »
Rozumné východisko je naučit se ty frameworky používat a neřešit věci, které není potřeba řešit a kterým nerozumíte. Pokud do výpisu seznamu přidáte ke každému prvku volání funkce, o které Vue nic neví, nezbývá mu nic jiného, než tu funkci pro každý prvek zavolat. To je ovšem vaše chyba, že tam tu funkci úplně zbytečně voláte. Přitom to máte napsané přímo v dokumentaci: Computed Caching vs Methods.

Mimochodem, to je přesně ten důvod, proč jsem psal, že se mi víc líbí přístup Reactu, kde musíte každý stav explicitně změnit. Z vašeho komentáře vyplynulo, že se vám víc líbí magie Vue, kdy se to „děje samo“. Ale teď na to narážíte, protože nerozumíte tomu, jak ta magie funguje, děláte tam nesmysly a na základě těchhle nesmyslů se to snažíte nesmyslně optimalizovat.

Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #8 kdy: 12. 06. 2021, 13:31:24 »
Compute jsem zkousel, ale to neni reseni. Me se jedna o metody volane uvnitr foreache, computed se nevola jako metoda, ale jako property.

A jak v tom pomuze React? Zkousel jsem to a chova se to stejne, upravim jen jeden radek z foreache, a metoda called() se zavola pro vsechny radky vzdy. Je to stejne chovani jako v magickem Vue.

Kód: [Vybrat]

import React from "react";
import ReactDOM from "react-dom";

class App extends React.Component {
  i = 0;
  constructor() {
    super();
    this.state = {
      arr: [
        { id: 0, val: 0 },
        { id: 1, val: 0 },
        { id: 2, val: 0 }
      ]
    };
  }

  called() {
    console.log("Called");
  }

  componentDidMount() {
    // setInterval(
    //   () => this.setState({ arr: [...this.state.arr, this.i++] }),
    //   1000
    // );
    setInterval(
      () =>
        this.setState({
          arr: this.state.arr.map((item) =>
            item.id === 0 ? { id: 0, val: this.i++ } : item
          )
        }),
      1000
    );
  }

  render() {
    return (
      <div>
        {this.state.arr.map((i) => (
          <div key={i.id}>
            {this.called()}
            {i.val}
          </div>
        ))}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("container"));




Citace
Rozumné východisko je naučit se ty frameworky používat a neřešit věci, které není potřeba řešit a kterým nerozumíte.

PS: Ja tady na to zakladam tema, a jak vidite, tak se to prave ucim pouzivat, a snazim se tomu rozumet - proto se tu na to ptam, proto tohle tema zakladam, jsem na diskuznm foru. Nevim, proc musite mit ustavicne takove utocne a curacke prupovidky - jste snad debil? Pokladam tady normalni, odrojakovany dotaz na vnitrni chovani tech frameworku.
« Poslední změna: 12. 06. 2021, 13:35:56 od registrovany123 »

Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #9 kdy: 12. 06. 2021, 13:51:51 »
Compute jsem zkousel, ale to neni reseni. Me se jedna o metody volane uvnitr foreache, computed se nevola jako metoda, ale jako property.
Netuším, čemu říkáte „volat jako property“. Computed property je normální funkce, která závisí na aktuálním stavu a vrací hodnotu. Díky tomu, že závisí na aktuálním stavu, ji Vue zavolá jenom tehdy, když se změní stav, který funkci ovlivňuje.


A jak v tom pomuze React? Zkousel jsem to a chova se to stejne, upravim jen jeden radek z foreache, a metoda called() se zavola pro vsechny radky vzdy. Je to stejne chovani jako v magickem Vue.
Reat tomu pomůže tak, že když chcete změnit stav, musíte explicitně zavolat funkci, která stav změní. Takže ji snad nebudete volat v případě, kdy se stav nezměnil (a když ji i přesto zavoláte, React pozná, že se nic nezměnilo, a nebude renderovací funkci volat zbytečně).

PS: Ja tady na to zakladam tema, a jak vidite, tak se to prave ucim pouzivat, a snazim se tomu rozumet - proto se tu na to ptam, proto tohle tema zakladam, jsem na diskuznm foru. Nevim, proc musite mit ustavicne takove utocne a curacke prupovidky - jste snad debil? Pokladam tady normalni, odrojakovany dotaz na vnitrni chovani tech frameworku.
Ne, nepokládáte normální dotazy. Nepřečetl jste si ani základní návody, vymyslel jste nesmyslný kód a teď na tom nesmyslu trváte. V šabloně nemáte volat žádné funkce, máte tam pracovat jenom se stavem.

Pokud se chcete Vue nebo React naučit používat, přečtěte si dokumentaci na jejich webu. Pak z vašeho kódu odstraňte to nesmyslné volání funkce v šabloně a budete mít po problému.

Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #10 kdy: 12. 06. 2021, 14:01:38 »
Dotaz neni stale zodpovezen. Ma se za to, ze jak React tak Vue udelaji vnitrne diff pri zmene stavu, a nasledne budou sahat jen do tech tagu, kterych se zmena stavu tyka. Muj kod dokazuje ze to tak uplne neni pravda jak pro React, tak pro Vue, a nikdo to tady neumi uplne vysvetlit.

Co se tyce volani funkci v template, asi tezko bude problem zavolat tam funkci napr. parseFloat(), je snad na to nekde nejake doporuceni, ze ani to se nema? Pokud bych mel tabulku o 1000 radku (coz bych klidne mohl), tak se mi bude 1000x volat parse float pri kazde jeden zmene Input Number ciselniku, kuprikladu. Proste upravim stav 1 itemu, a upravi se zbyvajicich 999 itemu.
« Poslední změna: 12. 06. 2021, 14:04:29 od registrovany123 »

Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #11 kdy: 12. 06. 2021, 14:07:27 »
Nevím jak ve Vue, v Reactu se to řešit dá. Například tak, že si člověk dá do Reduxu jednak objekt (asociativní pole) s obsahem klíč => řádek a pak pole klíčů, které určuje pořadí řádků. Pro každý řádek je komponenta a jako property má klíč řádku, který zobrazuje. Je napojená na Redux a z něj si z mapy příslušný řádek vyzvedne.

Tebou navrhovane reseni neni funkcni, zkousel jsem to a i React zavola metody ve foreach pri kazde aktualizaci stavu:

Kód: [Vybrat]
import React from "react";
import ReactDOM from "react-dom";

class App extends React.Component {
  i = 0;
  constructor() {
    super();
    this.state = {
      vals: [0, 1, 2],
      arr: [
        { id: 0, val: 0 },
        { id: 1, val: 0 },
        { id: 2, val: 0 }
      ]
    };
  }

  called() {
    console.log("Called");
  }

  componentDidMount() {
    // setInterval(
    //   () => this.setState({ arr: [...this.state.arr, this.i++] }),
    //   1000
    // );
    setInterval(
      () =>
        this.setState({
          arr: this.state.arr.map((item) =>
            item.id === 0 ? { id: 0, val: this.i++ } : item
          )
        }),
      1000
    );
  }

  render() {
    return (
      <div>
        {this.state.vals.map((i) => (
          <div key={i}>
            {this.called()}
            {this.state.arr[i].val}
          </div>
        ))}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("container"));


Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #12 kdy: 12. 06. 2021, 14:10:57 »
Takze principialni problem, predlozeny na zacatku, ze totiz mam tabulku o 5000 radcich, upravim item v 1 radku, a dojte k zavolani metod v cele tabulce, je stale platny, a navrhovane reseni v Reactu pomoci foreache ktery iteruje nad necim jinym, nez nad polozkami jednotlivych radku, se miji ucinkem.

Proto zatim jako jedine vychodisko vidim vytvorit separatni komponenty pro kazdy radek, nakopirovani props do stavu, a pridani tlacitka ulozit.

Rovnez zatim nevidim vyhodu pouziti Reactu namisto Vue.
« Poslední změna: 12. 06. 2021, 14:12:31 od registrovany123 »

Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #13 kdy: 12. 06. 2021, 14:31:32 »
Dotaz neni stale zodpovezen.
Odpověď na váš dotaz je, že máte chybně váš kód. V šabloně nemáte volat žádné funkce, jenom číst stav.

Ma se za to, ze jak React tak Vue udelaji vnitrne diff pri zmene stavu, a nasledne budou sahat jen do tech tagu, kterych se zmena stavu tyka.
Ne „m se za to“, ono to tak je.

Muj kod dokazuje ze to tak uplne neni pravda jak pro React, tak pro Vue, a nikdo to tady neumi uplne vysvetlit.
Ne, váš kód nic takového nedokazuje. Váš kód je za prvé špatně, za prvé se volá před vytvořením virtuálního DOMu, taže nevypovídá vůbec nic o tom, co se s virtuálním DOMem děje pak.

Co se tyce volani funkci v template, asi tezko bude problem zavolat tam funkci napr. parseFloat(), je snad na to nekde nejake doporuceni, ze ani to se nema?
Samozřejmě, že to bude problém. V šabloně máte jenom číst stav (ve Vue se tomu říká data), nic jiného.

První věta z dokumentace šablon Vue:
Citace
Vue.js uses an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying component instance's data.
Vidíte tam něco o renderování výsledku volání funkce? Ne, šablona slouží k renderování dat uložených v komponentě.

Pokud bych mel tabulku o 1000 radku (coz bych klidne mohl), tak se mi bude 1000x volat parse float pri kazde jeden zmene Input Number ciselniku, kuprikladu. Proste upravim stav 1 itemu, a upravi se zbyvajicich 999 itemu.
Ano, když to budete dělat svým špatným způsobem, bude se to volat tisíckrát.

Psal jste, že se to chcete naučit. Nebylo by tedy lepší udělat to správně, než trvat na svém špatném řešení?

Takze principialni problem, predlozeny na zacatku, ze totiz mam tabulku o 5000 radcich, upravim item v 1 radku, a dojte k zavolani metod v cele tabulce, je stale platny
Ano, stále platí, že váš kód je špatně, když při renderování šablony voláte funkce nezávislé na stavu.

Řešení je stále to stejné – nevolat tam tu nesmyslnou metodu, která nic nedělá. Žádné tlačítko uložit přidávat nemusíte.

Re:Jak v Reactu ci Vue modifikovat jen 1 radek vykreslene tabulky?
« Odpověď #14 kdy: 12. 06. 2021, 14:40:23 »
A co volani getteru v radcich tabulky? To je taky funkce. Pokud ani to nemuzu delat, tak v tom pripade nemuzu vubec pouzivat OOP.

Budu mit napriklad tridu FoodEntry, kde budu mit

getTotalCalories() {
  return this.amount / 100 * this.calories;
}

Podle vas tedy nemuzu delat ani tady to. A v tom pripade se mi zkomplikuje uplne vsechno.
« Poslední změna: 12. 06. 2021, 14:43:12 od registrovany123 »