I am using the following:
mui
5.2.7@mui/styles
5.2.5@emotion/react
11.7.1@emotion/styled
11.6.0react
17.0.2storybook
6.5.10and I am trying to reproduce a case where a mui InputLabel
component has its label shrunk on the top when passing a shrink
prop in a single select component. Here is an excerpt of the custom mui select component
<FormControl
{...rest}
className={`${classes.formControl} ${className}`}
error={error}
variant="standard"
>
{label && (
<InputLabel htmlFor={inputId} shrink={shrink} {...inputLabelProps}>
{label}
</InputLabel>
)}
<Select
input={<Input id={inputId} {...inputProps} />}
onChange={handleChange}
renderValue={renderValue}
value={value}
>
In tests and in the actual app everything works as expected but in storybook I receive the following error
react-dom.development.js:67 Warning: Received
true
for a non-boolean attributeshrink
.If you want to write it to the DOM, pass a string instead: shrink="true" or shrink={value.toString()}.
but the error makes no sense because the shrink
prop is declared as boolean and being passed like this both in app and unit tests.
and the input label is not shrunk when passing the relevant prop.
Here it the storybook code
function SingleTemplate(args) {
const [value, setValue] = useState("");
return (
<Box width={125}>
<EsaSelect label={label} onChange={setValue} options={options} value={value} {...args} />
</Box>
);
}
export const SingleSelectShrink = SingleTemplate.bind({});
SingleSelectShrink.args = { shrink: true };
I did not manage to reproduce the issue using this codesandbox. Actually there it works as expected but the configuration seems simpler than my local repository and it is a simplified version
I finally found that we might have an architecture problem in the way we render our Select components. At the moment we render 4 different components, a custom SingleSelect
, a custom MultiSelect
, a custom SingleAutocompleteSelect
and a custom MutliAutocompelteSelect
. These 4 components are over abstracted in one component. That means that if we want to invoke either of these 4 we call only one and then pass the desired props. Some are common but others are specific. However to achieve this we have some component specific props and then spreading the rest everywhere. This results to props of one component to end up in the props ofanother component which might not have the same API. Because we are using javascript and not typescript this works but it seems that storybook understands this differentiation and fires errors.
So what we do is something like this:
abstracted MySelect
component:
if (someProp1 || someProp2) {
return someProp3 ? (
<AutocompleteMultiSelect
{...rest}
cutomProp1={prop1}
customProp2={prop2}
/>
) : (
<AutocompleteSelect {...rest} customProp3={prop3} />
);
}
return anotherProp ? <MultiSelect {...rest} /> : <SingleSelect {...rest} />;
}