Reagu Aktualigitajn Ĝisdatigojn

Kiel kombini ŝtatajn ĝisdatigojn en sola redoni vokon

React.js batis ĝisdatigojn

Vi jam scias, ke kiam ajn vi ĝisdatigas la staton de ero, la diferenca algoritmo de React detektos ŝanĝojn en la virtuala DOM kaj redonos vian eron en la reala DOM. Sed ĉu vere ĉi tio okazas por ĉiu ŝtata ĝisdatigo? Aŭ ĉu Reagi provizas manieron batigi tiujn ĝisdatigojn, tiel ke multoblaj ŝtataj mutacioj kombiniĝas en ununura iga alvoko?

Sintezaj eventoj enkalkulas arajn ĝisdatigojn

React 17 kaj malsupre provizas me mechanismanismon por bati tiujn ĝisdatigojn. Vi vere ne devas multe pripensi ĝin dum kodado, sed scii kiel React povus optimumigi vian kodon estas tamen bonega lernado.

Jen kio okazas.

  • multnombraj ŝtataj mutacioj estas nomataj ene de revoko
  • se la revoko estas ligita al sinteza evento, React arigos tiujn mutaciojn
  • kiam mutacioj estas batitaj, nur unu redoni-vokon fariĝas
  • alie, ĉiu mutacio kondukas al nova bildigo

Por permesi batadon, viaj ŝtataj mutacioj devas esti nomataj ene de sinteza Reagokazaĵo. Kiel rapida memorigilo, sintezaj Reagaj eventoj estas esence nur ĉirkaŭaj denaskaj HTML-eventoj por doni la saman funkcion tra ĉiuj retumiloj. Ĉiu sinteza aranĝilo povas esti provizita rekte al ero kiel prop.

Por vidi ĉion en ago, jen ekzempla kodo, kiu permesus al React kombini ĉiujn ŝtatajn mutaciojn en ununuran redonadon, anstataŭ unu redonadon per mutacio.

function Component() {
  const [id, setId] = useState(0);
  const [date, setDate] = useState(new Date());
  const [random, setRandom] = useState(Math.random());

  // A lame callback, but it's just for
  // the demo. Note that clicking on the
  // button will only lead to a single
  // re-render!
  //
  // This is b/c the callback is provided to
  // 'onClick', a synthetic event.
  const onButtonClick = () => {
    setDate(new Date());
    setId(prevId => prevId + 1);
  }
  
  console.log("Render:", id, date);

  return (
    <div>
      <button 
        onClick={onButtonClick}>
        Update state
      </button>
    </div>
  );
}
//
// Almost the same as the previous
// example, but this time w/o
// a batched upate call.
//

function Component() {
  const [id, setId] = useState(0);
  const [date, setDate] = useState(new Date());
  const [random, setRandom] = useState(Math.random());

  // No batching, as the state
  // mutations happend inside
  // a setTimeout - even though
  // the timeout is inside a 
  // synthetic event.
  const onButtonClick = () => {
    setTimeout(() => {
      setDate(new Date());
      setId(prevId => prevId + 1);
    }, 0);
  }
  
  console.log("Render:", id, date);

  return (
    <div>
      <button 
        onClick={onButtonClick}>
        Update state
      </button>
    </div>
  );
}

Aktaj ĝisdatigoj por React 18 kaj poste

Kun la sekva versio de React (almenaŭ dum mi verkas ĉi tion), la batmekanismo estos multe pli plibonigita. Anstataŭ nur ebla en sintezaj eventoj, ankaŭ aliaj specoj de revokoj estos uzeblaj.

  • paŭzoj
  • promesoj
  • denaskaj aranĝantoj pri eventoj

Ĉi tiu ŝanĝo plej verŝajne kondukos al pli bona agado de via programo, ĉar malpli da bildigo fariĝos aŭtomate.

Evitante grupajn ĝisdatigojn en React 18 kaj poste

Komencante kun Reagi 18, vi havos la eblon eksplicite ekigi novan redonadon kun ĉiu ŝtata mutacio, do evitante grupan ĝisdatigon. Ĉi tio plej verŝajne estos uzata nur en randaj kazoj, sed tamen estas interese scii.

//  
// This example is almost
// 1:1 from Dan Abramov's
// example.
//
// Use 'flushSync' from the
// 'react-dom'-package.
import { flushSync } from 'react-dom'; 

function handleClick() {
  flushSync(() => {
    setId(prevId => prevId + 1);
  });
  // React has updated the DOM by now
  flushSync(() => {
    setDate(new Date());
  });
  // React has updated the DOM by now
}