mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
feat(switch): support for value and defaultValue props (#45747)
* feat(switch): support for `value` and `defaultValue` props * docs: update docs * chore: add unit case (cherry picked from commit d25977cd16e27949ccfe9f1533b3d16bb6c3abba) * chore: update case * chore: remove skip test case
This commit is contained in:
parent
53b4235796
commit
0da10b6cca
@ -2102,4 +2102,44 @@ describe('Form', () => {
|
||||
expect(container.querySelector('.ant-input-number-suffix')).toBeTruthy();
|
||||
expect(container.querySelector('.ant-input-number-focused')).toBeTruthy();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/20803#issuecomment-601626759
|
||||
it('without explicitly passing `valuePropName`', async () => {
|
||||
const submit = jest.fn();
|
||||
const Demo = () => (
|
||||
<Form
|
||||
initialValues={{
|
||||
foo: true,
|
||||
}}
|
||||
onFinish={submit}
|
||||
>
|
||||
<Form.Item label="Switch" name="foo">
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<button type="submit">Submit</button>
|
||||
</Form>
|
||||
);
|
||||
|
||||
const { getByRole } = render(<Demo />);
|
||||
|
||||
await waitFakeTimer();
|
||||
|
||||
const switchNode = getByRole('switch');
|
||||
|
||||
expect(switchNode).toBeTruthy();
|
||||
expect(switchNode).toBeChecked();
|
||||
|
||||
fireEvent.click(switchNode);
|
||||
expect(switchNode).not.toBeChecked();
|
||||
|
||||
const submitButton = getByRole('button');
|
||||
expect(submitButton).toBeTruthy();
|
||||
fireEvent.click(submitButton);
|
||||
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(submit).toHaveBeenCalledWith({
|
||||
foo: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -4,7 +4,6 @@ import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { act, fireEvent, render } from '../../../tests/utils';
|
||||
import { resetWarned } from '../../_util/warning';
|
||||
|
||||
jest.mock('rc-util/lib/Dom/isVisible', () => {
|
||||
const mockFn = () => true;
|
||||
@ -33,15 +32,35 @@ describe('Switch', () => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('warning if set `value`', () => {
|
||||
resetWarned();
|
||||
it('should be controlled by value', () => {
|
||||
const mockChangeHandler = jest.fn();
|
||||
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const props = { value: true } as any;
|
||||
render(<Switch {...props} />);
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Switch] `value` is not a valid prop, do you mean `checked`?',
|
||||
);
|
||||
errorSpy.mockRestore();
|
||||
const { getByRole } = render(<Switch value onChange={mockChangeHandler} />);
|
||||
|
||||
const switchNode = getByRole('switch');
|
||||
expect(switchNode).toBeTruthy();
|
||||
expect(getByRole('switch')).toBeChecked();
|
||||
|
||||
fireEvent.click(switchNode);
|
||||
|
||||
expect(mockChangeHandler).toHaveBeenCalledWith(false, expect.anything());
|
||||
// controlled component, so still true after click
|
||||
expect(getByRole('switch')).toBeChecked();
|
||||
});
|
||||
|
||||
it('should be uncontrolled by defaultValue', () => {
|
||||
const mockChangeHandler = jest.fn();
|
||||
|
||||
const { getByRole } = render(<Switch defaultValue onChange={mockChangeHandler} />);
|
||||
|
||||
const switchNode = getByRole('switch');
|
||||
expect(switchNode).toBeTruthy();
|
||||
expect(getByRole('switch')).toBeChecked();
|
||||
|
||||
fireEvent.click(switchNode);
|
||||
|
||||
expect(mockChangeHandler).toHaveBeenCalledWith(false, expect.anything());
|
||||
// uncontrolled component, so false after click
|
||||
expect(getByRole('switch')).not.toBeChecked();
|
||||
});
|
||||
});
|
||||
|
@ -29,19 +29,21 @@ Switching Selector.
|
||||
|
||||
Common props ref:[Common props](/docs/react/common-props)
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| autoFocus | Whether get focus when component mounted | boolean | false |
|
||||
| checked | Determine whether the Switch is checked | boolean | false |
|
||||
| checkedChildren | The content to be shown when the state is checked | ReactNode | - |
|
||||
| className | The additional class to Switch | string | - |
|
||||
| defaultChecked | Whether to set the initial state | boolean | false |
|
||||
| disabled | Disable switch | boolean | false |
|
||||
| loading | Loading state of switch | boolean | false |
|
||||
| size | The size of the Switch, options: `default` `small` | string | `default` |
|
||||
| unCheckedChildren | The content to be shown when the state is unchecked | ReactNode | - |
|
||||
| onChange | Trigger when the checked state is changing | function(checked: boolean, event: Event) | - |
|
||||
| onClick | Trigger when clicked | function(checked: boolean, event: Event) | - |
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| autoFocus | Whether get focus when component mounted | boolean | false | |
|
||||
| checked | Determine whether the Switch is checked | boolean | false | |
|
||||
| checkedChildren | The content to be shown when the state is checked | ReactNode | - | |
|
||||
| className | The additional class to Switch | string | - | |
|
||||
| defaultChecked | Whether to set the initial state | boolean | false | |
|
||||
| defaultValue | Alias for `defaultChecked` | boolean | - | 5.12.0 |
|
||||
| disabled | Disable switch | boolean | false | |
|
||||
| loading | Loading state of switch | boolean | false | |
|
||||
| size | The size of the Switch, options: `default` `small` | string | `default` | |
|
||||
| unCheckedChildren | The content to be shown when the state is unchecked | ReactNode | - | |
|
||||
| value | Alias for `checked` | boolean | - | 5.12.0 |
|
||||
| onChange | Trigger when the checked state is changing | function(checked: boolean, event: Event) | - | |
|
||||
| onClick | Trigger when clicked | function(checked: boolean, event: Event) | - | |
|
||||
|
||||
## Methods
|
||||
|
||||
|
@ -3,12 +3,12 @@ import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
|
||||
import classNames from 'classnames';
|
||||
import RcSwitch from 'rc-switch';
|
||||
|
||||
import { devUseWarning } from '../_util/warning';
|
||||
import Wave from '../_util/wave';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import DisabledContext from '../config-provider/DisabledContext';
|
||||
import useSize from '../config-provider/hooks/useSize';
|
||||
import useStyle from './style';
|
||||
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||
|
||||
export type SwitchSize = 'small' | 'default';
|
||||
export type SwitchChangeEventHandler = (
|
||||
@ -24,6 +24,16 @@ export interface SwitchProps {
|
||||
rootClassName?: string;
|
||||
checked?: boolean;
|
||||
defaultChecked?: boolean;
|
||||
/**
|
||||
* Alias for `checked`.
|
||||
* @since 5.12.0
|
||||
*/
|
||||
value?: boolean;
|
||||
/**
|
||||
* Alias for `defaultChecked`.
|
||||
* @since 5.12.0
|
||||
*/
|
||||
defaultValue?: boolean;
|
||||
onChange?: SwitchChangeEventHandler;
|
||||
onClick?: SwitchClickEventHandler;
|
||||
checkedChildren?: React.ReactNode;
|
||||
@ -53,18 +63,18 @@ const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>((props, ref) =>
|
||||
className,
|
||||
rootClassName,
|
||||
style,
|
||||
checked: checkedProp,
|
||||
value,
|
||||
defaultChecked: defaultCheckedProp,
|
||||
defaultValue,
|
||||
onChange,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const warning = devUseWarning('Switch');
|
||||
|
||||
warning(
|
||||
'checked' in props || !('value' in props),
|
||||
'usage',
|
||||
'`value` is not a valid prop, do you mean `checked`?',
|
||||
);
|
||||
}
|
||||
const [checked, setChecked] = useMergedState<boolean>(false, {
|
||||
value: checkedProp ?? value,
|
||||
defaultValue: defaultCheckedProp ?? defaultValue,
|
||||
});
|
||||
|
||||
const { getPrefixCls, direction, switch: SWITCH } = React.useContext(ConfigContext);
|
||||
|
||||
@ -99,10 +109,17 @@ const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>((props, ref) =>
|
||||
|
||||
const mergedStyle: React.CSSProperties = { ...SWITCH?.style, ...style };
|
||||
|
||||
const changeHandler: SwitchChangeEventHandler = (...args) => {
|
||||
setChecked(args[0]);
|
||||
onChange?.(...args);
|
||||
};
|
||||
|
||||
return wrapSSR(
|
||||
<Wave component="Switch">
|
||||
<RcSwitch
|
||||
{...restProps}
|
||||
checked={checked}
|
||||
onChange={changeHandler}
|
||||
prefixCls={prefixCls}
|
||||
className={classes}
|
||||
style={mergedStyle}
|
||||
|
@ -30,19 +30,21 @@ demo:
|
||||
|
||||
通用属性参考:[通用属性](/docs/react/common-props)
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| autoFocus | 组件自动获取焦点 | boolean | false |
|
||||
| checked | 指定当前是否选中 | boolean | false |
|
||||
| checkedChildren | 选中时的内容 | ReactNode | - |
|
||||
| className | Switch 器类名 | string | - |
|
||||
| defaultChecked | 初始是否选中 | boolean | false |
|
||||
| disabled | 是否禁用 | boolean | false |
|
||||
| loading | 加载中的开关 | boolean | false |
|
||||
| size | 开关大小,可选值:`default` `small` | string | `default` |
|
||||
| unCheckedChildren | 非选中时的内容 | ReactNode | - |
|
||||
| onChange | 变化时的回调函数 | function(checked: boolean, event: Event) | - |
|
||||
| onClick | 点击时的回调函数 | function(checked: boolean, event: Event) | - |
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| autoFocus | 组件自动获取焦点 | boolean | false | |
|
||||
| checked | 指定当前是否选中 | boolean | false | |
|
||||
| checkedChildren | 选中时的内容 | ReactNode | - | |
|
||||
| className | Switch 器类名 | string | - | |
|
||||
| defaultChecked | 初始是否选中 | boolean | false | |
|
||||
| defaultValue | `defaultChecked` 的别名 | boolean | - | 5.12.0 |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| loading | 加载中的开关 | boolean | false | |
|
||||
| size | 开关大小,可选值:`default` `small` | string | `default` | |
|
||||
| unCheckedChildren | 非选中时的内容 | ReactNode | - | |
|
||||
| value | `checked` 的别名 | boolean | - | 5.12.0 |
|
||||
| onChange | 变化时的回调函数 | function(checked: boolean, event: Event) | - | |
|
||||
| onClick | 点击时的回调函数 | function(checked: boolean, event: Event) | - | |
|
||||
|
||||
## 方法
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user