このようなUIコンポーネントのビルドを停止する❌


誰でも、コードベースで最も頻繁にコピーされたコードを再利用可能なコンポーネントに抽象化していると感じます.それの1つの悪い影響は別の日の物語である急いでいる抽象化です、今日の課題は実際に再利用可能な構成要素を作る方法を学ぶことです.
再利用可能なコンポーネントを抽象化しながら多くの時間それは小道具の混乱になります.あなたはおそらく50以上の小道具で“再利用可能な”コンポーネントを見てきた!これらの最後に非常に使用して維持するのは難しいが、同時にパフォーマンスの問題とは、追跡するのは難しいバグをもたらします.
新しいユースケースのための1つの支柱を加えることはちょうどif文でありません、そして、あなたはコードサイズを巨大で、保守できないようにしている構成要素の多くの変化を終えます.
しかし、我々が作成する抽象化の種類を意識しているならば、我々は本当に何かを本当に使いやすくて、維持することができて、バグがなくて、ユーザーがダウンロードペナルティを支払うほど大きくないです.
ケントCドッドの問題は、深さを説明して、時計を与える

再利用可能なコンポーネントはどのように見えますか?
私たちはLoginFormModal ログインフォームと登録フォームのモーダルを抽象化したコンポーネント.コンポーネント自体はすべて複雑ではなく、一握りの小道具を受け入れるだけですが、それはかなり柔軟性がありません、そして、我々はアプリケーションを通してより多くのmodalsを作成する必要があります.
<LoginFormModal
  onSubmit={handleSubmit}
  modalTitle="Modal title"
  modalLabelText="Modal label (for screen readers)"
  submitButton={<button>Submit form</button>}
  openButton={<button>Open Modal</button>}
/>

最後に、このように使用できるコンポーネントを作成します.
<Modal>
  <ModalOpenButton>
    <button>Open Modal</button>
  </ModalOpenButton>
  <ModalContents aria-label="Modal label (for screen readers)">
    <ModalDismissButton>
      <button>Close Modal</button>
    </ModalDismissButton>
    <h3>Modal title</h3>
    <div>Some great contents of the modal</div>
  </ModalContents>
</Modal>
しかし、ちょうどより多くのコードでなく、ちょうどprop😒.
我々は、創造者よりむしろコンポーネントのユーザーに責任を通過しました.それは間違いなく私たちの既存よりも使用するコードですLoginFormModal , しかし、それはより簡単で、より柔軟で、より複雑になることなく我々の将来のユースケースに合います.
例えば、我々はフォームをレンダリングするだけではない状況を考えますが
私たちが好きなものをレンダリングします.我々Modal これをサポートしますがLoginFormModal 新しい小道具を受け入れる必要があるでしょう.または、我々が閉じる必要があるならば
コンテンツの下に表示するボタン?と呼ばれる特別な支柱が必要だrenderCloseBelow . しかし、我々とModal , 明らかだ.あなたはちょうどModalCloseButton あなたがそれを行きたい場所へのコンポーネント.
はるかに柔軟で、より少ないAPI表面積.
このパターンは複合コンポーネントと呼ばれています.この古典的な例は<select> and <option> HTMLで.
このように多くの現実世界のライブラリで広く使われています.

  • Reach UI
  • MUI
  • 再利用を構築しながら、最初の複合成分をつくりましょうmodal .

    最初の複合成分の構築
    import * as React from 'react'
    import VisuallyHidden from '@reach/visually-hidden'
    
    /* Here the Dialog and CircleButton is a custom component 
    Dialog is nothing button some styles applied on reach-dialog 
    component provided by @reach-ui */
    import {Dialog, CircleButton} from './lib'
    
    const ModalContext = React.createContext()
    //this helps in identifying the context while visualizing the component tree
    ModalContext.displayName = 'ModalContext'
    
    function Modal(props) {
      const [isOpen, setIsOpen] = React.useState(false)
    
      return <ModalContext.Provider value={[isOpen, setIsOpen]} {...props} />
    }
    
    function ModalDismissButton({children: child}) {
      const [, setIsOpen] = React.useContext(ModalContext)
      return React.cloneElement(child, {
        onClick: () => setIsOpen(false),
      })
    }
    
    function ModalOpenButton({children: child}) {
      const [, setIsOpen] = React.useContext(ModalContext)
      return React.cloneElement(child, {
        onClick: () => setIsOpen(true),
    })
    }
    
    function ModalContentsBase(props) {
      const [isOpen, setIsOpen] = React.useContext(ModalContext)
      return (
        <Dialog isOpen={isOpen} onDismiss={() => setIsOpen(false)} {...props} />
      )
    }
    
    function ModalContents({title, children, ...props}) {
      return (
        //we are making generic reusable component thus we allowed user custom styles
       //or any prop they want to override
        <ModalContentsBase {...props}>
          <div>
            <ModalDismissButton>
              <CircleButton>
                <VisuallyHidden>Close</VisuallyHidden>
                <span aria-hidden>×</span>
              </CircleButton>
            </ModalDismissButton>
          </div>
          <h3>{title}</h3>
          {children}
        </ModalContentsBase>
      )
    }
    
    export {Modal, ModalDismissButton, ModalOpenButton, ModalContents}
    
    ああ!私たちはかなりの作業を行いました.
    <Modal>
         <ModalOpenButton>
             <Button>Login</Button>
         </ModalOpenButton>
         <ModalContents aria-label="Login form" title="Login">
             <LoginForm
                onSubmit={register}
                submitButton={<Button>Login</Button>}
              />
          </ModalContents>
      </Modal>
    
    コードは、より読みやすく、柔軟です.


    ボーナス:ユーザーが自分のOnClickHandlerを渡すことができます
    The ModalOpenButton and ModalCloseButton 設定するonClick彼らの子供のボタンのように我々は開くことができるとモードを閉じます.しかし、ユーザー
    これらのコンポーネントのうち、ユーザーがボタンをクリックしたときに何かをしたい
    例えば、モードの開閉に加えてください.
    このように渡されたすべてのメソッドを実行するコールallメソッドを作成します.
    callAll(() => setIsOpen(false), ()=>console.log("I ran"))
    
    私はケントからこれを学んだEpic React workshop . これはとても利口です.
    const callAll = (...fns) => (...args) => fns.forEach(fn => fn && fn(...args))
    
    コンポーネントでこれを使いましょう.
    function ModalDismissButton({children: child}) {
      const [, setIsOpen] = React.useContext(ModalContext)
      return React.cloneElement(child, {
        onClick: callAll(() => setIsOpen(false), child.props.onClick),
      })
    }
    
    function ModalOpenButton({children: child}) {
      const [, setIsOpen] = React.useContext(ModalContext)
      return React.cloneElement(child, {
        onClick: callAll(() => setIsOpen(true), child.props.onClick),
      })
    }
    
    電源は、onClickHandler このようなカスタムボタンに
    <ModalOpenButton>
      <button onClick={() => console.log('sending data to facebook ;)')}>Open Modal</button>
    </ModalOpenButton>
    


    結論
    急いで抽象化しないでくださいと小道具にすべてを残していない.多分それは単純なコンポーネントですが、あなたが将来的にカバーする必要がある使用ケースを知らない、これは時間と保守性の間のトレードオフとは思わない、複雑さは指数関数的に成長することができます.
    化合物成分と反応して、あなたの人生をより簡単に構成の力を活気づけてください.
    また、ケントのチェックEpic React Course 私は複合成分のパターンと多くのことを学んだ.
    私について少し私は厳しいです、そして、私はコードが好きです.私は16日からこれをしています.私は自宅で反応しながらウェブアプリを構築する.私は現在リミックスを学んでいます.
    あなたがブログが好きなら、接続しましょう!私は、将来、より多くのそのようなブログを持ってくる予定です.
    私についてもっと知ってくださいHarsh choudhary
    ブログやブログをチェックしてください.