alan2207 / bulletproof-react

🛡️ ⚛️ A simple, scalable, and powerful architecture for building production ready React applications.
MIT License
28.5k stars 2.58k forks source link

Question : How to make drawer globally? #145

Open galih56 opened 9 months ago

galih56 commented 9 months ago

Is it possible to make drawer globally and place the content wherever it's needed? Split the form and the drawer. For me, the drawer is not reusable enough. It will be great if I can call the drawer anywhere and place the content dynamically. For now, i can only use the drawer and place it to every single feature i want to make.

As example : In the code below, the FormDrawer must be used along with the form. But i want to create the form for separated from it and use it on other pages, like creatable select or some dialogs. I tried to split them, but i had a hard time syncing the mutation status because the useMutation is called inside parent component and the submit button is called inside the FormDrawer component. Any suggestions?

export const CreateTask = () => {
  const projectOptions = useProjectOptions();
  const tagOptions = useTagOptions();
  const usersOptions = useUserOptions();
  const createTaskMutation = useCreateTask();

  return (
      <FormDrawer
        isDone={createTaskMutation.isSuccess}
        triggerButton={
          <Button variant='primary' size="sm" icon={PlusIcon}>
            Create Task
          </Button>
        }
        title="Create Task"
        submitButton={
          <Button
            form="create-task"
            type="submit"
            size="sm"
            loading={createTaskMutation.isLoading}
          >
            Submit
          </Button>
        }
      >
        <Form<CreateTaskDTO['data'], typeof schema>
          id="create-task"
          onSubmit={async (values) =>  await createTaskMutation.mutateAsync({ data: values })}
          schema={schema}
        >
          {({ register, formState, control }) => (
            <>
              <SelectField
                label='Project'
                options={projectOptions}
                error={formState.errors['projectId']}
                registration={register('projectId')}
                control={control}
              />
              <InputField
                label="Title"
                error={formState.errors['title']}
                registration={register('title')}
              />
              <TextAreaField
                label="Description"
                error={formState.errors['description']}
                registration={register('description')}
              />

              <SelectField
                label='Tags'
                options={tagOptions}
                error={formState.errors['tags']}
                registration={register('tags')}
                control={control}
                multiple={true}
              />

              <SelectField
                label='Assignees'
                options={usersOptions}
                error={formState.errors['assignees']}
                registration={register('assignees')}
                control={control}
                multiple={true}
              />
            </>
          )}
        </Form>
      </FormDrawer>
  );
};
CamiloCagliolo commented 8 months ago

From my experience, I would place the drawer in the highest hierarchy component (App.jsx) and use a global state to decide wether I want to open it or not. If you want to customize its contents depending on where you are, you can pass additional information with that global state. For example, if it's a menu kind of drawer, maybe you can pass some information regarding available buttons like this:

[
   {
      icon: 'Home',
      text: 'Home',
      redirect: '/login',
   },
   {
      icon: 'Profile',
      text: 'Account',
      redirect: '/account',
    },
]

And so on and so forth. Then you can simply iterate over that array to build your buttons, passing the correct props to each.

It's completely possible that this can be improved. It's just the way I found.

Santosh130602 commented 5 months ago

hello @galih56 can i do work on this issue

alan2207 commented 5 months ago

Why do you need the drawer to be global? It is much easier to control it and its content when used on demand. I don't see the need for it to be global TBH...