storybook icon indicating copy to clipboard operation
storybook copied to clipboard

Controlled Input Loses Focus in Docs when Using useArgs Hook

Open jcq opened this issue 4 years ago • 14 comments

Describe the bug Using useArgs hook to update a controlled text input React component works fine on the "Canvas" tab, but when using it in Docs mode, we encounter an issue where the input loses focus after every key press (hence, every time the args are updated). This makes interacting with it in Docs mode extremely difficult.

To Reproduce Steps to reproduce the behavior:

  1. Go to Docs tab
  2. Click on the story for TextField component
  3. Attempt to type multiple characters into the input
  4. See error

Expected behavior The component should update the same within Docs as it does within the standard Canvas tab. The input should not lose focus when args are updated.

Screenshots If applicable, add screenshots to help explain your problem.

Code snippets Component:

import React from 'react';
import PropTypes from 'prop-types';

/**
 * Wrapper around a text input
 */
export const TextField = ({ label = 'Foo', value = '', onChange }) => {
  const handleChange = (event) => onChange?.(event.target.value);
  return (
    <React.Fragment>
      <label>{label}</label>
      <input type="text" value={value} onChange={handleChange} />
    </React.Fragment>
  );
};

TextField.propTypes = {
  /**
   * Text to use as a label
   */
  label: PropTypes.string,
  /**
   * Value controlled externally to component
   */
  value: PropTypes.string,
  /**
   * Change handler
   */
  onChange: PropTypes.func,
};

TextField.defaultProps = {};

Story:

import React from 'react';

import { useArgs } from '@storybook/client-api';

import { TextField } from './TextField';

export default {
  title: 'Controlled TextField',
  component: TextField,
  argTypes: {},
};

const Template = (args) => {
  const [_args, updateArgs] = useArgs();
  const handleChange = (value) => updateArgs({ value });

  return <TextField {...args} onChange={handleChange} />;
};

export const Basic = Template.bind({});
Basic.args = {
  value: 'foo',
  label: 'Lorem ipsum',
};

System: Please paste the results of npx -p @storybook/cli@next sb info here.

Environment Info:
(node:73572) UnhandledPromiseRejectionWarning: TypeError: e.filter is not a function
    at /Users/jcq/.npm/_npx/73241/lib/node_modules/@storybook/cli/node_modules/envinfo/dist/envinfo.js:1:73205
    at async Promise.all (index 6)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:73572) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:73572) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

😅

I'm using @storybook/* 6.0.0-rc.14 with latest create-react-app.

Additional context I've created a repo that demonstrates the issue

jcq avatar Jul 23 '20 01:07 jcq

Is this still an issue in the latest release @jcq?

shilman avatar Sep 24 '20 08:09 shilman

Is this still an issue in the latest release @jcq?

Yeah, this problem still exists :(

Momomash avatar Sep 24 '20 09:09 Momomash

Possible dupe to https://github.com/storybookjs/storybook/issues/12255

shilman avatar Sep 25 '20 10:09 shilman

Is this issue fixed? I'm experiencing it on 6.1.0-alpha.16

y-nk avatar Oct 27 '20 16:10 y-nk

Nope, issue's still open

shilman avatar Oct 28 '20 05:10 shilman

I think this is a dupe of #12255 -- if I add the decorator:

  decorators: [(Story) => <Story />],

To your story, I see the same issue in canvas mode. If I change the decorator to:

  decorators: [(Story) => Story()],

the issue goes away (in Canvas).

So I wonder if docs mode is rendering the story in such a way to trigger the same rendering issue.

tmeasday avatar Nov 05 '20 07:11 tmeasday

I have a very similar problem with useEffect triggering a onChange event, which in turn triggers updateArgs, again. The values never change, but the component gets remounted. Also, it happens only in Docs mode, but not in Canvas mode. It seems to have the same cause.

fabiradi avatar Jun 22 '21 15:06 fabiradi

This hasn't been fixed yet in 6.3.4. I think the reason is that updateArgs triggers a re-render of the args table, which is in the same container as the story, causing that one to be re-rendered too, which causes the focus to be lost.

As proof I tried adding:

parameters: {
    docs: {
      inlineStories: false,
    }
  }

Then the story is rendered in an iframe, which makes the updateArgs work, but then a change of the controls doesn't update the story. The reason this doesn't happen in the canvas is because the addons-drawer is not in the same container as the story.

orjandesmet avatar Jul 14 '21 14:07 orjandesmet

Still an issue in 6.3.12. Was able to fix it for my textfield component by adding an autoFocus, but that isn't an option for other components. Like @orjandesmet mentioned, it appears that after a change, the whole component re-renders, thus losing the focus. Seems like the change of the controls should not cause a full rerender, but rather only pass the new props down.

I've also noticed that this rendering/update pattern causes any component using the updateArgs to sometimes get unbearably slow causing the whole browser to lag. This is not surprising if the entire component is constantly re-rendering completely instead of just updating.

runfaj avatar Jan 07 '22 17:01 runfaj

Still seeing this in 6.5.0-beta.7 any updates?

CoreyRo avatar May 10 '22 17:05 CoreyRo

Hi there, I am facing the same issue in Docs section: component is unmounted / re-mounted after args update, which causes some components used in the decorator to be re-rendered. Does anyone have a workaround or is a fix planned? Thx to the team !

fredericvilcot avatar May 12 '22 19:05 fredericvilcot

Ok, I took another look. You can observe this behaviour in the official-storybook story core-rendering--args-change if you:

a) make it the primary storybook for the component (remove the Counter story) b) turn off features.modernInlineRender. c) increment the first arg in the controls panel.

As such, I think the issue is fixed by features.modernInlineRender. Can the folks who are seeing the issue please try using that? It will be the default in 7.0 and we are unlikely to spend much time fixing any issues in the legacy inline render mechanism.

tmeasday avatar May 13 '22 05:05 tmeasday

@tmeasday Turning on features.modernInlineRender in .storybook/main.ts immediately solves this issue, as you predicted above:

module.exports = {
  stories: ['../stories/**/*.stories.mdx', '../stories/**/*.stories.@(ts|tsx)'],
  addons: ['@storybook/preset-scss', '@storybook/addon-links', '@storybook/addon-essentials'],
  features: {
    modernInlineRender: true
  }

Story is rendered as expected without any unmouting cycle at args update 👌

fredericvilcot avatar May 13 '22 08:05 fredericvilcot

@tmeasday @fredericvilcot I've enabled modernInlineRender however I'm still experiencing the issue in Storybook 6.5.9 (for React).

oogali avatar Jun 22 '22 11:06 oogali

Having this issue too. Any idea if this is getting fixed in v7?

jagoncalves14 avatar Jan 06 '23 14:01 jagoncalves14

@jagoncalves14 I guess we need to confirm if it is still an issue with modernInlineRender (which is the way it works in v7).

@oogali do you have a reproduction of the problem? (or @jagoncalves14?)

tmeasday avatar Jan 07 '23 00:01 tmeasday

I was experiencing the same problem and modernInlineRender fixed it for me (Storybook v6.5.16)

gvdp avatar Feb 10 '23 08:02 gvdp

I upgraded the repro to 7.0 and the problem is fixed there. I would advise folks to either upgrade or use modernInlineRender. Thanks!

tmeasday avatar Feb 12 '23 22:02 tmeasday

I am using v7 and experiencing this problem, please advice.

"storybook": "^7.0.18",

support for modernInlineRender has been removed post v6 and v7 doesn't work.

somandubey avatar Jun 20 '23 09:06 somandubey

@somandubey the "modern" rendering is the only option in SB7. If you are seeing an issue in SB7 I'd suggest opening a new ticket for it with a reproduction.

tmeasday avatar Jun 20 '23 23:06 tmeasday

thanks @tmeasday for your quick response. it worked eventually. please ignore the request.

somandubey avatar Jun 21 '23 14:06 somandubey