Skip to content

Instantly share code, notes, and snippets.

@yarastqt
Created July 12, 2022 20:14
Show Gist options
  • Save yarastqt/0d7557307d436437d17d25a3f60f404e to your computer and use it in GitHub Desktop.
Save yarastqt/0d7557307d436437d17d25a3f60f404e to your computer and use it in GitHub Desktop.
import { FC, createContext, useContext } from 'react';
export function createModelFactory<T extends (...args: any[]) => any>(creator: T) {
type Model = ReturnType<typeof creator>;
type ModelProps = { model: Model };
const Context = createContext<Model | null>(null);
function useModel() {
const model = useContext(Context);
if (!model) {
throw new Error('Model not found.');
}
return model;
}
function view<T>(Component: FC<T>) {
return (props: T & ModelProps) => (
<Context.Provider value={props.model}>
<Component {...props} />
</Context.Provider>
);
}
return {
createModel: creator,
useModel,
view,
};
}
@yarastqt
Copy link
Author

Usage

Declare model:

import { createEvent, sample } from 'effector';

import { createDialogApi } from '@client/shared/libs/effector-helpers/dialog';
import { createModelFactory } from '@client/shared/libs/effector-helpers/view-model-factory';

export const factory = createModelFactory(() => {
  const dialog = createDialogApi();

  const confirm = createEvent();
  const confirmed = createEvent();
  const declined = createEvent();

  sample({
    clock: confirm,
    target: dialog.show,
  });

  sample({
    clock: [confirmed, declined],
    target: dialog.hide,
  });

  return {
    dialog,
    confirm,
    confirmed,
    declined,
  };
});

Declare view:

import { useEvent, useStore } from "effector-react";

import { factory } from "./model";

interface DeleteConfirmationDialogProps {}

export const DeleteConfirmationDialog =
  factory.view<DeleteConfirmationDialogProps>((props) => {
    const { cover, text } = props;

    const model = factory.useModel();

    const onConfirm = useEvent(model.confirmed);
    const onDecline = useEvent(model.declined);

    const isVisible = useStore(model.dialog.$isVisible);

    return (
      <Dialog visible={isVisible} onClose={onDecline}>
        <Button size="xl" variant="default" onPress={onConfirm}>
          Удалить
        </Button>

        <Button size="xl" variant="clear" onPress={onDecline}>
          Оставить всё как есть
        </Button>
      </Dialog>
    );
  });

Apply:

const deleteConfirmationModel = factory.create()

<DeleteConfirmationDialog model={deleteConfirmationModel} />

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