Reagovat Hooks:Co se stane s renderováním rekvizit?

Asi před rokem jsem publikoval "Jak poskytnout uživatelům kontrolu vykreslování pomocí prop getterů". V tomto příspěvku ukazuji celou implementaci (v té době) react-toggled který jsem ve skutečnosti vytvořil pouze za účelem výuky některých vzorů, které jsem použil vdownshift . Je to mnohem menší a jednodušší komponenta, která implementuje mnoho stejných vzorů jako podřazování soit sloužilo jako skvělý způsob, jak naučit vzor rekvizit.

Jak přepínání reakcí, tak řazení dolů používají vzor vykreslování jako mechanismus pro sdílení logického kódu komponenty React. Jak jsem vysvětlil ve svém příspěvku na blogu „Kdy NEPOUŽÍVAT Render Props“, jedná se o primární případ použití vzoru render prop. Ale to je také primární případ použití pro React Hooks. A React Hooks jsou MNOHEM jednodušší než classcomponents + render rekvizity.

Znamená to tedy, že když jsou React Hooks stabilní, nebudete už vůbec potřebovat rekvizity pro renderování? Ne! Napadají mě dva scénáře, kde bude vzor vykreslování stále velmi užitečný, a o ty se s vámi za chvíli podělím. Ale pojďme dál a doložme své tvrzení, že háčky jsou jednodušší, porovnáním aktuální verze react-toggled s implementací založenou na hácích.

Pokud máte zájem, zde je aktuální zdroj pro react-toggled .

Zde je typické použití react-toggled :

function App() {
  return (
    <Toggle>
      {({on, toggle}) => <button onClick={toggle}>{on ? 'on' : 'off'}</button>}
    </Toggle>
  )
}

Pokud bychom chtěli pouze jednoduchou funkci přepínání, naše verze háku by byla:

function useToggle(initialOn = false) {
  const [on, setOn] = useState(initialOn)
  const toggle = () => setOn(!on)
  return {on, toggle}
}

Pak by to lidé mohli používat takto:

function App() {
  const {on, toggle} = useToggle()
  return <button onClick={toggle}>{on ? 'on' : 'off'}</button>
}

Chladný! Mnohem jednodušší! Ale komponenta Toggle v přepínání reakcí ve skutečnosti podporuje mnohem více. Jednak poskytuje pomocníka s názvem getTogglerProps který vám poskytne správné rekvizity, které potřebujete, aby přepínač fungoval (včetně aria atributy pro přístupnost). Tak ať to funguje:

// returns a function which calls all the given functions
const callAll =
  (...fns) =>
  (...args) =>
    fns.forEach(fn => fn && fn(...args))

function useToggle(initialOn = false) {
  const [on, setOn] = useState(initialOn)
  const toggle = () => setOn(!on)
  const getTogglerProps = (props = {}) => ({
    'aria-expanded': on,
    tabIndex: 0,
    ...props,
    onClick: callAll(props.onClick, toggle),
  })
  return {
    on,
    toggle,
    getTogglerProps,
  }
}

A nyní naše useToggle hook může použít getTogglerProps :

function App() {
  const {on, getTogglerProps} = useToggle()
  return <button {...getTogglerProps()}>{on ? 'on' : 'off'}</button>
}

A je to dostupnější a tak. Pěkné, že? No, co když nepotřebuji getTogglerProps pro můj případ použití? Pojďme to trochu rozdělit:

// returns a function which calls all the given functions
const callAll =
  (...fns) =>
  (...args) =>
    fns.forEach(fn => fn && fn(...args))

function useToggle(initialOn = false) {
  const [on, setOn] = useState(initialOn)
  const toggle = () => setOn(!on)
  return {on, toggle}
}

function useToggleWithPropGetter(initialOn) {
  const {on, toggle} = useToggle(initialOn)
  const getTogglerProps = (props = {}) => ({
    'aria-expanded': on,
    tabIndex: 0,
    ...props,
    onClick: callAll(props.onClick, toggle),
  })
  return {on, toggle, getTogglerProps}
}

A totéž bychom mohli udělat pro podporu getInputTogglerProps agetElementTogglerProps pomocníci, kteří react-toggled aktuálně podporuje. To by nám ve skutečnosti umožnilo snadno setřást ty nadbytečné nástroje, které naše aplikace nepoužívá, což by bylo dost neergonomické dělat s řešením renderprops (ne nemožné, jen trochu ošklivé).

Ale Kente! Nechci jít a refaktorovat všechna místa v mé aplikaci, která používají rozhraní API pro vykreslování pro použití nového rozhraní API pro háky!!

Nikdy se nebojte! Podívejte se na toto:

const Toggle = ({children, ...props}) => children(useToggle(props))

Tady máš komponentu pro renderování. Můžete jej použít stejně jako ten starý a časem migrovat. Ve skutečnosti takto doporučuji testovat vlastní háčky!

Je toho trochu víc (například jak portujeme vzor kontrolních rekvizit pro reakci háčků). To nechám na vás, abyste to objevili. Jakmile si to na chvíli vyzkoušíte, pak se dívejte, jak to dělám. Způsob, jakým jsme věci testovali, má háček, který se lehce mění s háčky (díky uzávěrům JavaScriptu).

Zbývající případ použití rekvizit vykreslování

Dobře, takže můžeme refaktorovat naše komponenty tak, aby používaly háky, a dokonce pokračovat v exportu reakčních komponent pomocí API založeného na renderovacím prop (možná by vás to zajímalo, možná byste mohli zvážit použití vzoru hydra). Ale představme si, že jsme v budoucnosti, kde nepotřebujeme renderovací rekvizity pro opětovné použití logiky a všichni používají háčky. Existuje nějaký důvod, proč pokračovat v psaní nebo používání komponent, které odhalují rozhraní API pro renderování?

ANO! Pozorovat! Zde je příklad použití řazení dolů s reagovat virtualizací. Zde je relevantní bit:

<List
  // ... some props
  rowRenderer={({key, index, style}) => (
    <div
    // ... some props
    />
  )}
/>

Podívejte se na rowRenderer rekvizita tam. Víš co to je? JE TO RENDERPROP! Co!? 🙀 To je inverze ovládání v celé své kráse s vykreslením vrtule. To je rekvizita, která react-virtualized používá k delegování řízení vykreslování řádků v seznamu na vás uživatele komponenty. Pokudreact-virtualized měly být přepsány tak, aby používaly háčky, možná mohl by přijmout rowRenderer jako argument pro useVirtualized hák, ale ve skutečnosti v tom nevidím žádnou výhodu oproti současnému API. Takže si myslím, že rekvizity vykreslování (a tento styl inverze ovládání) tu zůstanou pro případy použití jako je tento.

Závěr

Doufám, že vám to přijde zajímavé a užitečné. Pamatujte, že háky React jsou stále ve verzi alfa a mohou se změnit. Jsou také zcela přihlášeni a nebudou vyžadovat žádné změny v rozhraní API Reactu. Myslím, že je to skvělá věc. Nepřepisujte své aplikace! Refaktorujte je (jakmile jsou háčky stabilní)!

Hodně štěstí!