Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@bem-react/di: Improve DX [RFC] #507

Open
1 task
yarastqt opened this issue Dec 28, 2019 · 3 comments
Open
1 task

@bem-react/di: Improve DX [RFC] #507

yarastqt opened this issue Dec 28, 2019 · 3 comments
Assignees

Comments

@yarastqt
Copy link
Member

yarastqt commented Dec 28, 2019

Можно немного ослабить связь между view и di убрав напрямую обращение в useComponentRegistry(id) из @bem-react/di, т.к. у нас все сущности хранятся в реестре, а реестр хранится рядом с компонентом, то можно делать как-то так:

App/registry/index.ts

import { FC } from 'react'
import { createRegistry, createDepsHook } from '@bem-react/di'

type AppDeps = {
  Button: FC<any>
  Input: FC<any>
}

// Тут просто заменил конструктор на фабрику, внутри можно генерировать id,
// т.к. по факту этот id больше нигде не используется, если нужно будет
// переопределить какой-то компонент в эксперименте, можно сделать форк реестра.
export const registry = createRegistry<AppDeps>()
// Хелпер, который внутри себя вызывает useComponentRegistry.
export const useDeps = createDepsHook<AppDeps>(registry.id)

// Можно сделать альтертативный вариант, возвращать тапл:
export const [registry, useDeps] = createRegistry<AppDeps>()

App/registry/desktop.tsx

import { registry as emptyRegistry } from './index'

// Метод fork копирует полностью реестр, по аналогии с merge,
// но в качестве аргумента принимает хэшсет с компонентами.
export const registry = emptyRegistry.fork({
  Button: () => <button>login</button>,
  Input: () => <input placeholder="email" />,
})

// Либо альтертативный вариант:
export const registry = emptyRegistry
  .fork()
  .fill({
    Button: () => <button>login</button>,
    Input: () => <input placeholder="email" />,
  })

App.tsx

import { useDeps } from './registry/index'

export const App = () => {
  // Тут мы ничего не знаем про реализацию DI,
  // просто берем зависимости из своего реестра,
  // к тому же имеем сразу вывод типов.
  const { Button, Input } = useDeps()
  
  return (
    <>
      <Button />
      <Input />
    </>
  )
}

App@desktop.tsx

import { withRegistry } from '@bem-react/di'
import { registry } from './App/registry/desktop'
import { App as AppCommon } from './App'

export const App = withRegistry(registry)(App)

TODO

  • Подумать как использовать с компонентами на классах
@yarastqt yarastqt added the RFC label Dec 28, 2019
@yarastqt
Copy link
Member Author

Так же метод fork позволит не пересоздавать руками заново реестр с переопределениями и не указывать для него нужный интерфейс.

@belozer
Copy link
Member

belozer commented Dec 28, 2019

> `export const useDeps = createDepsHook<AppDeps>(registry.id)`

мне кажется, что это равносильно

> export const useDeps = () => useComponentRegistry<AppDeps>(registry.id)

@yarastqt
Copy link
Member Author

Ну... да :) можно вообще это все инкапсулировать внутри фабрики для создания реестра

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants