在遵循了本教程building-a-checkbox-component-with-react-and-styled-components之后,我正在使用React,Typescript,Storybook和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。任何帮助将不胜感激。
答案 0 :(得分:0)
解决方案是将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
,复选框将正确显示。