From 9a7fc96245bc05999ee2f0754eb02540ea183d09 Mon Sep 17 00:00:00 2001 From: xliez Date: Tue, 2 Jan 2024 23:27:03 +0800 Subject: [PATCH] feat: support custom label render (#995) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: support custom label render * fix: update tests & demo & doc * Update src/Select.tsx Co-authored-by: Amumu * fix: demo * fix: ci lint Signed-off-by: xliez * fix: hooks deps & format demo * test: 测试用例调整 * chore: fix lint Signed-off-by: xliez * test: 添加测试用例 --------- Signed-off-by: xliez Co-authored-by: Amumu --- README.md | 1 + docs/demo/custom-label.md | 8 +++++ docs/examples/custom-label.tsx | 66 ++++++++++++++++++++++++++++++++++ src/Select.tsx | 6 ++-- tests/Select.test.tsx | 65 +++++++++++++++++++++++++++++++++ 5 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 docs/demo/custom-label.md create mode 100644 docs/examples/custom-label.tsx diff --git a/README.md b/README.md index 6a27c9ce..55c589b0 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ export default () => ( | virtual | Disable virtual scroll | boolean | true | | direction | direction of dropdown | 'ltr' \| 'rtl' | 'ltr' | | optionRender | Custom rendering options | (oriOption: FlattenOptionData\ , info: { index: number }) => React.ReactNode | - | +| labelRender | Custom rendering label | (props: LabelInValueType) => React.ReactNode | - | | maxCount | The max number of items can be selected | number | - | ### Methods diff --git a/docs/demo/custom-label.md b/docs/demo/custom-label.md new file mode 100644 index 00000000..ad1a7635 --- /dev/null +++ b/docs/demo/custom-label.md @@ -0,0 +1,8 @@ +--- +title: custom-label +nav: + title: Demo + path: /demo +--- + + diff --git a/docs/examples/custom-label.tsx b/docs/examples/custom-label.tsx new file mode 100644 index 00000000..d7b5b9fd --- /dev/null +++ b/docs/examples/custom-label.tsx @@ -0,0 +1,66 @@ +/* eslint-disable no-console */ +import Select, { Option } from 'rc-select'; +import React from 'react'; +import '../../assets/index.less'; + +const children = []; +for (let i = 10; i < 36; i += 1) { + children.push( + , + ); +} + +const Test: React.FC = () => { + const [value, setValue] = React.useState('test'); + + return ( +
+

custom label render

+ +
+ +
+

+ +

+
+ ); +}; + +export default Test; +/* eslint-enable */ diff --git a/src/Select.tsx b/src/Select.tsx index ee91bc50..b5c87c67 100644 --- a/src/Select.tsx +++ b/src/Select.tsx @@ -149,6 +149,7 @@ export interface SelectProps React.ReactNode; // >>> Icon menuItemSelectedIcon?: RenderNode; @@ -199,6 +200,7 @@ const Select = React.forwardRef ({ ...item, - label: item.label ?? item.value, + label: (typeof labelRender === 'function' ? labelRender(item) : item.label) ?? item.value, })); - }, [mode, mergedValues]); + }, [mode, mergedValues, labelRender]); /** Convert `displayValues` to raw value type set */ const rawValues = React.useMemo( diff --git a/tests/Select.test.tsx b/tests/Select.test.tsx index f856f4b0..413c80bf 100644 --- a/tests/Select.test.tsx +++ b/tests/Select.test.tsx @@ -1,3 +1,4 @@ +import type { LabelInValueType } from '@/Select'; import { fireEvent, render as testingRender } from '@testing-library/react'; import { mount, render } from 'enzyme'; import KeyCode from 'rc-util/lib/KeyCode'; @@ -2115,6 +2116,70 @@ describe('Select.Basic', () => { ); }); + it('labelRender', () => { + const onLabelRender = jest.fn(); + const labelRender = (props: LabelInValueType) => { + const { label, value } = props; + onLabelRender(); + return `${label}-${value}`; + }; + const wrapper = mount( + ); + + expect(onLabelRender).toHaveBeenCalled(); + expect(findSelection(wrapper).text()).toEqual('fakeLabel-a'); + }); + + it('labelRender when labelInValue and useCache', () => { + const onLabelRender = jest.fn(); + const labelRender = (props: LabelInValueType) => { + const { label, value } = props; + onLabelRender({ label, value }); + return `custom label`; + }; + + const wrapper = mount( +