storybook [Bug]: 当故事渲染函数使用args参数时,React组件似乎被挂载了两次,

fiei3ece  于 5个月前  发布在  React
关注(0)|答案(2)|浏览(56)

描述问题

在使用 Storybook 故事的渲染函数中的 args 参数时,React 组件似乎被挂载了两次。这种行为导致了一些问题,尤其是在使用自定义钩子直接在故事中时。

重现步骤

  1. 转到提供的 StackBlitz link
  2. 打开 Button stories WorkingNot Working 并观察浏览器控制台,查看两个故事的不同行为。
  • 正常工作: 在每次点击按钮后一秒钟,渲染函数中的钩子按预期工作,它会向控制台记录一条消息。
  • 不正常工作: 组件似乎被挂载了两次。一个示例似乎表现正常,另一个示例没有更新其状态。结果是每次点击只记录一次,每秒点击记录两次。两个故事之间唯一的区别似乎是 args 参数被传递到渲染函数中。

https://stackblitz.com/edit/github-56csk3?file=stories%2FButton.stories.tsx

系统信息

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
  Binaries:
    Node: 16.20.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.4.2 - /usr/local/bin/npm
  npmPackages:
    @storybook/addon-essentials: ^7.4.0-alpha.0 => 7.4.0-alpha.0 
    @storybook/addon-interactions: ^7.4.0-alpha.0 => 7.4.0-alpha.0 
    @storybook/addon-links: ^7.4.0-alpha.0 => 7.4.0-alpha.0 
    @storybook/addon-onboarding: ^1.0.8 => 1.0.8 
    @storybook/blocks: ^7.4.0-alpha.0 => 7.4.0-alpha.0 
    @storybook/nextjs: ^7.4.0-alpha.0 => 7.4.0-alpha.0 
    @storybook/react: ^7.4.0-alpha.0 => 7.4.0-alpha.0 
    @storybook/testing-library: ^0.2.0 => 0.2.0

其他上下文

我理解观察到的行为可能是有意为之,也可能受到自定义钩子实现的影响。虽然我已经尽力将问题缩小到最佳范围,但可能还有我不了解的因素可能导致这种行为。
对于如何解决这个问题的建议、指导或想法将受到极大的重视。提前感谢您的帮助。

tvokkenx

tvokkenx1#

我也遇到了这个问题。看起来函数参数甚至不需要被使用,因为它们是在函数上定义的,这足以导致它渲染两次。
我找到了一个解决方法,如果你把所有的函数参数都放入一个单独的rest参数中,故事似乎只渲染一次。这不太好看,但对我有效。
这会导致故事渲染两次:

export const MyStory = (args) => {...};

但是这将使故事只渲染一次(如预期):

export const MyStory = (...[args]) => { ... }
w1jd8yoj

w1jd8yoj2#

确认args导致挂载两次。每次args - 相同的对象。

let argsMemorized: object | undefined = undefined

const CheckedIcon: React.FC = (args) => {
  if (argsMemorized === undefined) {
    console.log("no argsMemorized")
    argsMemorized = args
  }

  useEffect(() => {
    console.log("CheckedIcon mounted args", args)
    console.log(
      "CheckedIcon mounted args === argsMemorized",
      args === argsMemorized
    )

    return () => {
      console.log("CheckedIcon unmounted")
    }
  }, [args])

  return <Renderer src={checkedIcon.src} />
}

输出:

no argsMemorized
(index):75 Renderer mounted
(index):107 CheckedIcon mounted args {}
(index):108 CheckedIcon mounted args === argsMemorized true
(index):107 CheckedIcon mounted args {}
(index):108 CheckedIcon mounted args === argsMemorized true

并确认,这个解决方法有效。

相关问题