反应故事书复选框更改处理程序不起作用
Posted
技术标签:
【中文标题】反应故事书复选框更改处理程序不起作用【英文标题】:React Storybook Checkbox change handler not working 【发布时间】:2020-07-05 19:42:21 【问题描述】:在遵循本教程之后,我正在使用 React、Typescript、Storybook 和 Styled-Components 创建一个复选框组件:building-a-checkbox-component-with-react-and-styled-components。在使用 FunctionComponent 时,我不得不调整代码,但我遇到了更改处理程序的问题。我无法选中或取消选中似乎是只读的复选框,而且我不确定我哪里出错了。这是我的代码:
Checkbox.tsx
import React from 'react';
import styled from 'styled-components';
import FunctionComponent from 'react';
type CheckboxProps =
checked?: boolean;
onChange: (e: React.ChangeEvent<htmlInputElement>) => void;
;
const CheckboxContainer = styled.div`
display: inline-block;
vertical-align: middle;
`;
const Icon = styled.svg`
fill: none;
stroke: white;
stroke-width: 2px;
`;
const HiddenCheckbox = styled.input.attrs( type: 'checkbox' )`
border: 0;
clip: rect(0 0 0 0);
clippath: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
white-space: nowrap;
width: 1px;
`;
const StyledCheckbox = styled.div`
display: inline-block;
width: 16px;
height: 16px;
background: $(props: CheckboxProps) => (props.checked ? 'green' : 'white');
border-color: 'dark gray';
border-width: 1px;
border-style: solid;
border-radius: 2px;
$HiddenCheckbox:focus + &
box-shadow: 0 0 0 3px grey;
$Icon
visibility: $(props: CheckboxProps) => (props.checked ? 'visible' : 'hidden');
`;
const Checkbox: FunctionComponent<CheckboxProps> = ( onChange, checked, ...props ) =>
return (
<CheckboxContainer>
<HiddenCheckbox checked=checked ...props onChange=onChange />
<StyledCheckbox data-testid="styledcheckbox" checked=checked ...props onChange=onChange>
<Icon viewBox="0 0 24 24">
<polyline points="20 6 9 17 4 12" />
</Icon>
</StyledCheckbox>
</CheckboxContainer>
);
;
export default Checkbox;
Checkbox.stories.js
// Checkbox.stories.js
import React, useState, useRef from 'react';
import Checkbox from '@components/Checkbox/Checkbox';
import action from '@storybook/addon-actions';
import storiesOf from '@storybook/react';
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const CheckboxStateful = props =>
const [value, setValue] = useState(props);
const valRef = useRef(value);
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const onChange = event =>
setValue(event.target.value);
valRef.current = event.target.value;
;
return (
<Checkbox
value=value
onChange=event =>
onChange(event);
></Checkbox>
);
;
storiesOf('Checkbox', module)
.add('with checked', () =>
const value = true;
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const onChange = event => setValue(event.target.value);
return <CheckboxStateful value=value onChange=onChange></CheckboxStateful>;
)
.add('with unchecked', () =>
const value = false;
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const onChange = event => setValue(event.target.value);
return <CheckboxStateful value=value onChange=onChange></CheckboxStateful>;
);
由于我是 React 和 Storybook 的新手,我可能需要一些专家的意见来确定我的更改处理程序代码是否正确。我看过其他示例,但没有一个使用 Typescript。任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:解决方法是在Checkbox.tsx中将CheckboxProps中的onChange改为onClick,如下:
onClick: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
并将 Checkbox.stories.js 中的 CheckboxStateful 简化如下:
const CheckboxStateful = () =>
const [value, setValue] = useState(false);
return <Checkbox checked=value onClick=() => setValue(!value)></Checkbox>;
;
现在完整的更新代码如下:
Checkbox.tsx
import * as React from 'react';
import styled from 'styled-components';
import FunctionComponent from 'react';
type CheckboxProps =
checked?: boolean;
onClick: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
;
const CheckboxContainer = styled.div`
display: inline-block;
vertical-align: middle;
`;
const Icon = styled.svg`
fill: none;
stroke: white;
stroke-width: 2px;
`;
const HiddenCheckbox = styled.input.attrs( type: 'checkbox' )`
border: 0;
clip: rect(0 0 0 0);
clippath: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
white-space: nowrap;
width: 1px;
`;
const StyledCheckbox = styled.div`
display: inline-block;
width: 16px;
height: 16px;
background: $(props: CheckboxProps) => (props.checked ? 'green' : 'white');
border-color: 'dark gray';
border-width: 1px;
border-style: solid;
border-radius: 2px;
$HiddenCheckbox:focus + &
box-shadow: 0 0 0 3px grey;
$Icon
visibility: $(props: CheckboxProps) => (props.checked ? 'visible' : 'hidden');
`;
const Checkbox: FunctionComponent<CheckboxProps> = ( onClick, checked, ...props ) =>
return (
<CheckboxContainer>
<HiddenCheckbox checked=checked ...props />
<StyledCheckbox checked=checked ...props onClick=onClick data-testid="styledcheckbox">
<Icon viewBox="0 0 24 24">
<polyline points="20 6 9 17 4 12" />
</Icon>
</StyledCheckbox>
</CheckboxContainer>
);
;
export default Checkbox;
Checkbox.stories.js
/* eslint-disable @typescript-eslint/explicit-function-return-type */
// Checkbox.stories.js
import * as React from 'react';
import useState from 'react';
import Checkbox from '@components/Checkbox/Checkbox';
import action from '@storybook/addon-actions';
import storiesOf from '@storybook/react';
export default
title: 'Checkbox',
component: Checkbox,
;
const CheckboxStateful = () =>
const [value, setValue] = useState(false);
return <Checkbox checked=value onClick=() => setValue(!value)></Checkbox>;
;
storiesOf('Checkbox', module)
.add('with checked', () =>
const value = true;
return <Checkbox checked=value onClick=action('checked')></Checkbox>;
)
.add('with unchecked', () =>
const value = false;
return <Checkbox checked=value onClick=action('checked')></Checkbox>;
)
.add('stateful', () =>
return <CheckboxStateful />;
);
创建 React 项目并添加 Storybook 后,只需运行 yarn storybook
,复选框就会正确显示。
【讨论】:
我不会将其称为修复,而是称为 hack。复选框有一个onChange
函数。【参考方案2】:
与其创建新的有状态组件,更好的方法是在组件模板中使用状态。
一个例子:
const Template: ComponentStory<typeof MyComponent> = (args) =>
const [state, setState] = useState('');
return (
<MyComponent
prop1=args.prop1
prop2=args.prop2
onChange=() => setState('Change')
/>
);
;
这是我从以下方法获得的原始答案的链接: https://***.com/a/64722559/10641401
【讨论】:
以上是关于反应故事书复选框更改处理程序不起作用的主要内容,如果未能解决你的问题,请参考以下文章
next-i18next 翻译在故事书中不起作用,控制台日志丢失键
带有旋钮的角故事书(storybookjs/addons/knobs)带有select()的对象数组不起作用