Controlled Input Loses Focus in Docs when Using useArgs Hook
See original GitHub issueDescribe 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:
- Go to Docs tab
- Click on the story for
TextField
component - Attempt to type multiple characters into the input
- 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
Issue Analytics
- State:
- Created 3 years ago
- Reactions:11
- Comments:14 (7 by maintainers)
Top GitHub Comments
@tmeasday Turning on
features.modernInlineRender
in.storybook/main.ts
immediately solves this issue, as you predicted above:Story is rendered as expected without any unmouting cycle at args update 👌
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:
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.