Reageer opgedateerde opdaterings

Hoe om staatsopdaterings in 'n enkele oproep te kombineer

Opgedateerde opdaterings van React.js

U weet reeds dat wanneer u die toestand van 'n komponent opdateer, die veranderende algoritme van React veranderinge in die virtuele DOM sal opspoor en u komponent in die werklike DOM sal weergee. Maar gebeur dit werklik vir elke staatsopdatering? Of bied React 'n manier om hierdie opdaterings te groepeer, sodat veelvuldige staatsmutasies in 'n enkele weergawe -oproep gekombineer word?

Sintetiese gebeurtenisse maak voorsiening vir bondelopdaterings

Reageer 17 en laer bied 'n meganisme om hierdie opdaterings te batch. U hoef regtig nie baie daaroor na te dink tydens die kodering nie, maar om te weet hoe React u kode kan optimaliseer, is tog 'n goeie leer.

Hier is wat gebeur.

  • veelvuldige staatsmutasies word binne 'n terugbel gebel
  • as die terugbel gekoppel is aan 'n sintetiese gebeurtenis, sal React die mutasies plaas
  • as mutasies in groepe geplaas word, word slegs 'n enkele oproep gemaak
  • anders lei elke mutasie tot 'n nuwe weergawe

U moet u staatsmutasies in 'n sintetiese React-gebeurtenis ontbied om batching moontlik te maak. As 'n vinnige herinnering, is sintetiese React-geleenthede basies net 'n omhulsel rondom inheemse HTML-gebeurtenisse om dieselfde funksionaliteit in alle blaaiers te bied. Elke sintetiese gebeurtenishanteerder kan as 'n rekwisiet direk aan 'n komponent verskaf word.

Om dit alles in aksie te sien, is hier 'n voorbeeldkode waarmee React alle staatsmutasies in 'n enkele weergawe kan kombineer, in plaas van een weergawe per mutasie.

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>
  );
}

Gedeelde opdaterings vir React 18 en later

Met die volgende weergawe van React (ten minste terwyl ek dit skryf), sal die bondelmeganisme baie meer verbeter word. In plaas daarvan dat dit slegs moontlik is in sintetiese geleenthede, sal ander tipes terugbel ook bruikbaar wees.

  • tydsbepalings
  • beloftes
  • inheemse gebeurtenishanteerders

Hierdie verandering sal waarskynlik lei tot 'n beter prestasie van u app, aangesien minder weergawe outomaties gedoen sal word.

Vermy batch -opdaterings in React 18 en later

Begin met React 18, sal u die opsie hê om eksplisiet 'n nuwe weergawe by elke staatsmutasie te aktiveer, en daarom moet u 'n batch -opdatering vermy. Dit sal waarskynlik slegs in randgevalle gebruik word, maar dit is nietemin interessant om te weet.

//  
// 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
}