storybook icon indicating copy to clipboard operation
storybook copied to clipboard

[Bug]: Typescript optional function is not default to undefined in story

Open aliakbarazizi opened this issue 1 year ago • 5 comments

Describe the bug

When I create a component and set a property to optional function and then try to test the story I see storybook create a mock function and sent it to component as default

For example

interface Props{
   onChange?: () => void
}

And here is code generated from storybook

<Component onChange={() => {}} />

Even in example that generate by default, in Button component onClick is optional but storybook still ignore it and add it by default even when argTypes and args are empty

Im not sure What i should to reproduce as this issue exist in the default example in Button component

To Reproduce

https://stackblitz.com/github/storybookjs/sandboxes/tree/next/react-vite/default-ts/after-storybook?file=src%2Fstories%2FButton.stories.ts&preset=node

System

No response

Additional context

No response

aliakbarazizi avatar Jun 05 '23 22:06 aliakbarazizi

This is a problem with how Storybook's Source block works today. It's taking the React element that is the result of rendering the story and trying to turn that into a string. As far as I know those functions don't stringify cleanly, so we just put () => {} as a placeholder. We are open to suggestions about how we might do this differently.

shilman avatar Jun 07 '23 01:06 shilman

This is a problem with how Storybook's Source block works today. It's taking the React element that is the result of rendering the story and trying to turn that into a string. As far as I know those functions don't stringify cleanly, so we just put () => {} as a placeholder. We are open to suggestions about how we might do this differently.

I don't think it should be () => {}, because I mark the parameter as optional, so It should be never defined at all.

aliakbarazizi avatar Jun 07 '23 01:06 aliakbarazizi

@shilman I think this could be improved. The optional prop onChange that the user has not specified, is provided to the React component, actually by ArgsEnhancers in @storybook/addon-actions and @storybook/addon-interactions. The additional args provided by these addons are merged into context.initialArgs, which originally only contains what the user has specified in story's args. So if we could track separately the args that users have explicitly provided in their stories (separate from those added by addons and enhancers, etc), we're able to use this information to generate code snippets that only contains user-specified props, in the docs page.

I'm planning to write a feature request for this, so I'll let you know once more when I submit it.

sookmax avatar Jul 05 '23 07:07 sookmax

I think I am having the same issue here using Storybook 6.5.X. Here's the short version of ours:

"use client";
import React, { useState } from "react";

export interface BarChartProps extends BaseChartProps {
+  onValueChange?: (value: any) => void;
}

const BarChart = React.forwardRef<HTMLDivElement, BarChartProps>((props, ref) => {
  const {
    data = [],
    categories = [],
+  onValueChange,
    className,
    ...other
  } = props;
  const [activeBar, setActiveBar] = React.useState<any | undefined>(undefined);

  function onBarClick(data: any, index: number, event: React.MouseEvent) {
    event.stopPropagation();

+  if (onValueChange == null) return; // not working, because onValueChange in not undefined, but "ƒ () {return fn2.apply(this, arguments);}"
    if (deepEqual(activeBar, data.tooltipPosition)) {
      setActiveBar(undefined);
    } else {
      setActiveBar(data.tooltipPosition);
      onValueChange?.({
        ...data.payload,
        dataKeyClicked: data.tooltipPayload[0]?.dataKey,
      });
    }
  }
  const yAxisDomain = getYAxisDomain(autoMinValue, minValue, maxValue);

  return (
    <div ref={ref} className={tremorTwMerge("w-full h-80", className)} {...other}>
      <ResponsiveContainer className="h-full w-full">
        {data?.length ? (
          <ReChartsBarChart
        // ...

severinlandolt avatar Sep 18 '23 07:09 severinlandolt

Same issue here. Even when I define the prop with undefined in the default story, it still applies the mock function, and therefore rendering something conditionally with the prop does not work. Any updates on this?

noranda avatar Feb 17 '24 22:02 noranda

Also running into this, was a bit confused why my conditional logic didn't work in Storybook, and found this issue.

EDIT: My function was named onHelpClicked and I had actions: { argTypesRegex: '^on[A-Z].*' }, in my preview.tsx file, removing that fixed it ... but I don't really want to remove it. Oh well.

MarcBridner avatar Feb 26 '24 20:02 MarcBridner