mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-31 09:44:21 +00:00
[change] modernize Picker
Rewrite Picker to use function components and hooks. Rewrite the tests to replace enzyme with testing-library.
This commit is contained in:
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
import type { ColorValue } from '../../types';
|
import type { ColorValue } from '../../types';
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import createElement from '../createElement';
|
import createElement from '../createElement';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -20,10 +19,8 @@ type Props = {
|
|||||||
value?: number | string
|
value?: number | string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class PickerItem extends React.Component<Props> {
|
export default function PickerItem(props: Props) {
|
||||||
render() {
|
const { color, label, testID, value } = props;
|
||||||
const { color, label, testID, value } = this.props;
|
const style = { color };
|
||||||
const style = { color };
|
return createElement('option', { style, testID, value }, label);
|
||||||
return createElement('option', { style, testID, value }, label);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-10
@@ -9,14 +9,9 @@ exports[`components/Picker prop "children" items 1`] = `
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`components/Picker prop "children" renders items 1`] = `
|
exports[`components/Picker prop "children" renders items 1`] = `
|
||||||
Array [
|
<option
|
||||||
<PickerItem
|
value="value-1"
|
||||||
label="label-1"
|
>
|
||||||
value="value-1"
|
label-1
|
||||||
/>,
|
</option>
|
||||||
<PickerItem
|
|
||||||
label="label-2"
|
|
||||||
value="value-2"
|
|
||||||
/>,
|
|
||||||
]
|
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
/* eslint-env jasmine, jest */
|
/* eslint-env jasmine, jest */
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { render } from '@testing-library/react';
|
||||||
import Picker from '..';
|
import Picker from '..';
|
||||||
|
|
||||||
|
function findSelect(container) {
|
||||||
|
return container.querySelector('select');
|
||||||
|
}
|
||||||
|
|
||||||
describe('components/Picker', () => {
|
describe('components/Picker', () => {
|
||||||
describe('prop "children"', () => {
|
describe('prop "children"', () => {
|
||||||
test('renders items', () => {
|
test('renders items', () => {
|
||||||
@@ -13,14 +17,14 @@ describe('components/Picker', () => {
|
|||||||
<Picker.Item label="label-2" value="value-2" />
|
<Picker.Item label="label-2" value="value-2" />
|
||||||
</Picker>
|
</Picker>
|
||||||
);
|
);
|
||||||
const component = shallow(picker);
|
const { container } = render(picker);
|
||||||
expect(component.children()).toMatchSnapshot();
|
expect(container.firstChild.firstChild).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('items', () => {
|
test('items', () => {
|
||||||
const pickerItem = <Picker.Item label="label-1" value="value-1" />;
|
const pickerItem = <Picker.Item label="label-1" value="value-1" />;
|
||||||
const component = shallow(pickerItem);
|
const { container } = render(pickerItem);
|
||||||
expect(component).toMatchSnapshot();
|
expect(container.firstChild).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -32,8 +36,8 @@ describe('components/Picker', () => {
|
|||||||
<Picker.Item label="label-2" value="value-2" />
|
<Picker.Item label="label-2" value="value-2" />
|
||||||
</Picker>
|
</Picker>
|
||||||
);
|
);
|
||||||
const component = shallow(picker);
|
const { container } = render(picker);
|
||||||
expect(component.find('select').prop('disabled')).toBe(true);
|
expect(findSelect(container).disabled).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -46,11 +50,14 @@ describe('components/Picker', () => {
|
|||||||
<Picker.Item label="label-2" value="value-2" />
|
<Picker.Item label="label-2" value="value-2" />
|
||||||
</Picker>
|
</Picker>
|
||||||
);
|
);
|
||||||
const component = shallow(picker);
|
const { container } = render(picker);
|
||||||
component.find('select').simulate('change', {
|
const select = findSelect(container);
|
||||||
target: { selectedIndex: '1', value: 'value-2' }
|
// mock change event
|
||||||
});
|
select.selectedIndex = '1';
|
||||||
expect(onValueChange).toHaveBeenCalledWith('value-2', '1');
|
select.value = 'value-2';
|
||||||
|
select.dispatchEvent(new window.Event('change', { bubbles: true }));
|
||||||
|
|
||||||
|
expect(onValueChange).toHaveBeenCalledWith('value-2', 1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -62,8 +69,8 @@ describe('components/Picker', () => {
|
|||||||
<Picker.Item label="label-2" value="value-2" />
|
<Picker.Item label="label-2" value="value-2" />
|
||||||
</Picker>
|
</Picker>
|
||||||
);
|
);
|
||||||
const component = shallow(picker);
|
const { container } = render(picker);
|
||||||
expect(component.find('select').prop('value')).toBe('value-2');
|
expect(findSelect(container).value).toBe('value-2');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('selects the correct item (number)', () => {
|
test('selects the correct item (number)', () => {
|
||||||
@@ -73,8 +80,8 @@ describe('components/Picker', () => {
|
|||||||
<Picker.Item label="label-2" value={22} />
|
<Picker.Item label="label-2" value={22} />
|
||||||
</Picker>
|
</Picker>
|
||||||
);
|
);
|
||||||
const component = shallow(picker);
|
const { container } = render(picker);
|
||||||
expect(component.find('select').prop('value')).toBe(22);
|
expect(findSelect(container).value).toBe('22');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+43
-35
@@ -10,11 +10,12 @@
|
|||||||
|
|
||||||
import type { ViewProps } from '../View';
|
import type { ViewProps } from '../View';
|
||||||
|
|
||||||
import applyNativeMethods from '../../modules/applyNativeMethods';
|
|
||||||
import { Component } from 'react';
|
|
||||||
import createElement from '../createElement';
|
import createElement from '../createElement';
|
||||||
|
import setAndForwardRef from '../../modules/setAndForwardRef';
|
||||||
|
import usePlatformMethods from '../../hooks/usePlatformMethods';
|
||||||
import PickerItem from './PickerItem';
|
import PickerItem from './PickerItem';
|
||||||
import StyleSheet, { type StyleObj } from '../StyleSheet';
|
import StyleSheet, { type StyleObj } from '../StyleSheet';
|
||||||
|
import { forwardRef, useRef } from 'react';
|
||||||
|
|
||||||
type PickerProps = {
|
type PickerProps = {
|
||||||
...ViewProps,
|
...ViewProps,
|
||||||
@@ -29,44 +30,51 @@ type PickerProps = {
|
|||||||
prompt?: string
|
prompt?: string
|
||||||
};
|
};
|
||||||
|
|
||||||
class Picker extends Component<PickerProps> {
|
const Picker = forwardRef<PickerProps, *>((props, ref) => {
|
||||||
static Item = PickerItem;
|
const {
|
||||||
|
children,
|
||||||
|
enabled,
|
||||||
|
onValueChange,
|
||||||
|
selectedValue,
|
||||||
|
style,
|
||||||
|
testID,
|
||||||
|
/* eslint-disable */
|
||||||
|
itemStyle,
|
||||||
|
mode,
|
||||||
|
prompt,
|
||||||
|
/* eslint-enable */
|
||||||
|
...other
|
||||||
|
} = props;
|
||||||
|
|
||||||
render() {
|
const hostRef = useRef(null);
|
||||||
const {
|
const setRef = setAndForwardRef({
|
||||||
children,
|
getForwardedRef: () => ref,
|
||||||
enabled,
|
setLocalRef: c => {
|
||||||
selectedValue,
|
hostRef.current = c;
|
||||||
style,
|
}
|
||||||
testID,
|
});
|
||||||
/* eslint-disable */
|
usePlatformMethods(hostRef, ref, null, style);
|
||||||
itemStyle,
|
|
||||||
mode,
|
|
||||||
prompt,
|
|
||||||
onValueChange,
|
|
||||||
/* eslint-enable */
|
|
||||||
...otherProps
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return createElement('select', {
|
function handleChange(e: Object) {
|
||||||
children,
|
|
||||||
disabled: enabled === false ? true : undefined,
|
|
||||||
onChange: this._handleChange,
|
|
||||||
style: [styles.initial, style],
|
|
||||||
testID,
|
|
||||||
value: selectedValue,
|
|
||||||
...otherProps
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleChange = (e: Object) => {
|
|
||||||
const { onValueChange } = this.props;
|
|
||||||
const { selectedIndex, value } = e.target;
|
const { selectedIndex, value } = e.target;
|
||||||
if (onValueChange) {
|
if (onValueChange) {
|
||||||
onValueChange(value, selectedIndex);
|
onValueChange(value, selectedIndex);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
|
||||||
|
return createElement('select', {
|
||||||
|
children,
|
||||||
|
disabled: enabled === false ? true : undefined,
|
||||||
|
onChange: handleChange,
|
||||||
|
ref: setRef,
|
||||||
|
style: [styles.initial, style],
|
||||||
|
testID,
|
||||||
|
value: selectedValue,
|
||||||
|
...other
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Picker.Item = PickerItem;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
initial: {
|
initial: {
|
||||||
@@ -76,4 +84,4 @@ const styles = StyleSheet.create({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default applyNativeMethods(Picker);
|
export default Picker;
|
||||||
|
|||||||
Reference in New Issue
Block a user