bbbtech / storybook-formik

A storybook decorator that allows you to use components in your stories that rely on Formik context.
53 stars 17 forks source link

Certain props seem to not be passed down #20

Closed Je12emy closed 3 years ago

Je12emy commented 3 years ago

Hello friend, I've been using this decorator for a while, and I'm really enjoying it. I'm working on fixing a few errors I left in my code due to time constrains and I found out that certain formik props are not being passed down to my form like isSubmitting.

Here's my code for a small signing form.

const SigninForm: React.FC<FormikProps<SigninFormValues>> = (props) => {
  const { isSubmitting, handleSubmit } = props;
  const [usernameField, usernameMeta] = useField("username");
  const [passwordField, passwordMeta] = useField("password");

  return (
    <div className="flex flex-col bg-white p-4 shadow rounded-lg justify-center">
      <form onSubmit={handleSubmit}>
        <Input
          {...usernameField}
          {...usernameMeta}
          errorMsg={usernameMeta.error}
          name={usernameField.name}
          leftIcon={() => <HiUser />}
          placeholder="Nombre de usuario"
        />
        {
         // other fields....
         }
        <Button title="Ingresar" loading={isSubmitting} />
      </form>
    </div>
  );
};

Here a loading spinner is shown when isSubmitting is set to true, here's a screenshot on how it should look like:

image

But when using the decorator when submitting my form this does not occur, the isSubmitting prop is undefined and the decorator does indicate my form is submitting.

image

Here's the code for my story

export default {
  title: "Authentication/Form",
  component: SignInForm,
  decorators: [withFormik],
} as Meta;

const Template: Story<FormikProps<SigninFormValues>> = (args) => (
  <SignInForm {...args} />
);

export const Default = Template.bind({});

Default.parameters = {
  formik: {
    initialValues: {
      username: "",
      password: "",
    },
    validationSchema: signinSchema,
    validateOnBlur: true,
    validateOnChange: true,
    onSubmit: (values: any, { setSubmitting }: any) => {
      setTimeout(() => {
        setSubmitting(false);
      }, 5000);
    },
  },
};

This is a bit nitpicky, so I don't think it causes too much trouble, but I was still wondering if this was an error on my side or maybe something else.

bhishp commented 3 years ago

Hi @Je12emy thanks for your detailed issue and code examples. I think the problem here is the SignInForm props. In your example, you define your component like this:

const SigninForm: React.FC<FormikProps<SigninFormValues>> = (props) => {
  const { isSubmitting, handleSubmit } = props;

It seems the component is expecting FormikProps to be passed as the component, but this decorator does not pass the formik render props directly to the story, it just wraps the story in a context provider. The question is, how are you using this Form in your codebase? Do you pass the formik Props directly to it?

One way you could get around this is to change the Component itself to rely on useFormikContext, rather than by relying on FormikProps to be passed directly. So, in your example, switch out the top of the component as follows:

const SigninForm: React.FC = (props) => {
  const { isSubmitting, handleSubmit } = useFormikContext();
  const [usernameField, usernameMeta] = useField("username");
  const [passwordField, passwordMeta] = useField("password");

  ...
}

This will mean that the form will hook-in to the withFormik decorator context within the story, and will also give you the flexibility to avoid needing to prop-drill the formik props wherever you use this form. As the component already uses useField, also hooking into the formik context isn't a problem I'd say.

If this is not what you want to do then maybe there could be a way to add another decorator that does useFormikContext from outside of the component - somewhere in storybook- and then injects the props, but I have quickly experimented with this and it seems storybook is doing some magic under-the-hood so this won't work easily.

I hope that helps

bhishp commented 3 years ago

Closing due to inactivity

javierguzman commented 3 years ago

"If this is not what you want to do then maybe there could be a way to add another decorator that does useFormikContext from outside of the component - somewhere in storybook- and then injects the props, but I have quickly experimented with this and it seems storybook is doing some magic under-the-hood so this won't work easily."

Hello @bhishp do you think with Storybook 7 will be easier to make this feature? I actually have "sub-forms" where I pass formik props and I have been scratching my head how to make this work on Storybook. I thought this addon would help but as you have mentioned the addon does not pass the formik props to the story.

Thank you in advance and regards

bhishp commented 3 years ago

Hi @javierguzman I'm afraid that I have not been keeping up-to-date with Storybook releases, is there specific features of SB7 that you think may help this case? I am also not actively developing with Formik either so my knowledge of the library has become stale.

javierguzman commented 3 years ago

Being honest I cannot recall why I asked about Storybook 7. I know they were making some big changes but no idea which one was related to this as I wrote it two weeks ago. If I remember it again I will come back