From 0ffed39027d504aea4ab2ca0364e73d5851131dd Mon Sep 17 00:00:00 2001 From: Oleksandr Fediashov Date: Tue, 3 Aug 2021 14:12:03 +0200 Subject: [PATCH] chore(Search*): use React.forwardRef() (#4270) --- src/index.js | 1 + src/modules/Search/Search.js | 2 + src/modules/Search/SearchCategory.js | 8 ++-- src/modules/Search/SearchCategoryLayout.d.ts | 5 +- src/modules/Search/SearchCategoryLayout.js | 1 + src/modules/Search/SearchResult.js | 48 +++++++++---------- src/modules/Search/SearchResults.js | 7 +-- .../modules/Search/SearchCategory-test.js | 1 + .../Search/SearchCategoryLayout-test.js | 13 +++++ .../specs/modules/Search/SearchResult-test.js | 14 ++++++ .../modules/Search/SearchResults-test.js | 1 + 11 files changed, 67 insertions(+), 34 deletions(-) create mode 100644 test/specs/modules/Search/SearchCategoryLayout-test.js diff --git a/src/index.js b/src/index.js index e4f85c45cb..e7c6d2ebcc 100644 --- a/src/index.js +++ b/src/index.js @@ -154,6 +154,7 @@ export RatingIcon from './modules/Rating/RatingIcon' export Search from './modules/Search' export SearchCategory from './modules/Search/SearchCategory' +export SearchCategoryLayout from './modules/Search/SearchCategoryLayout' export SearchResult from './modules/Search/SearchResult' export SearchResults from './modules/Search/SearchResults' diff --git a/src/modules/Search/Search.js b/src/modules/Search/Search.js index 8739f7041b..c417395b05 100644 --- a/src/modules/Search/Search.js +++ b/src/modules/Search/Search.js @@ -22,6 +22,7 @@ import { } from '../../lib' import Input from '../../elements/Input' import SearchCategory from './SearchCategory' +import SearchCategoryLayout from './SearchCategoryLayout' import SearchResult from './SearchResult' import SearchResults from './SearchResults' @@ -683,5 +684,6 @@ Search.defaultProps = { Search.autoControlledProps = ['open', 'value'] Search.Category = SearchCategory +Search.CategoryLayout = SearchCategoryLayout Search.Result = SearchResult Search.Results = SearchResults diff --git a/src/modules/Search/SearchCategory.js b/src/modules/Search/SearchCategory.js index da0fef015e..71d9c01224 100644 --- a/src/modules/Search/SearchCategory.js +++ b/src/modules/Search/SearchCategory.js @@ -11,8 +11,9 @@ import { } from '../../lib' import SearchCategoryLayout from './SearchCategoryLayout' -function SearchCategory(props) { +const SearchCategory = React.forwardRef(function (props, ref) { const { active, children, className, content, layoutRenderer, renderer } = props + const classes = cx(useKeyOnly(active, 'active'), 'category', className) const rest = getUnhandledProps(SearchCategory, props) const ElementType = getElementType(SearchCategory, props) @@ -21,17 +22,18 @@ function SearchCategory(props) { const resultsContent = childrenUtils.isNil(children) ? content : children return ( - + {layoutRenderer({ categoryContent, resultsContent })} ) -} +}) SearchCategory.defaultProps = { layoutRenderer: SearchCategoryLayout, renderer: ({ name }) => name, } +SearchCategory.displayName = 'SearchCategory' SearchCategory.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/src/modules/Search/SearchCategoryLayout.d.ts b/src/modules/Search/SearchCategoryLayout.d.ts index 1f39a001a6..75ae6fffa4 100644 --- a/src/modules/Search/SearchCategoryLayout.d.ts +++ b/src/modules/Search/SearchCategoryLayout.d.ts @@ -1,8 +1,5 @@ import * as React from 'react' -import { SemanticShorthandContent } from '../../generic' -import SearchResult from './SearchResult' - export interface SearchCategoryLayoutProps extends StrictSearchCategoryLayoutProps { [key: string]: any } @@ -15,6 +12,6 @@ export interface StrictSearchCategoryLayoutProps { resultsContent: React.ReactElement } -declare const SearchCategoryLayout: React.StatelessComponent +declare const SearchCategoryLayout: React.FunctionComponent export default SearchCategoryLayout diff --git a/src/modules/Search/SearchCategoryLayout.js b/src/modules/Search/SearchCategoryLayout.js index 4f0a3cf63f..b83dee804c 100644 --- a/src/modules/Search/SearchCategoryLayout.js +++ b/src/modules/Search/SearchCategoryLayout.js @@ -3,6 +3,7 @@ import React from 'react' function SearchCategoryLayout(props) { const { categoryContent, resultsContent } = props + return ( <>
{categoryContent}
diff --git a/src/modules/Search/SearchResult.js b/src/modules/Search/SearchResult.js index d967cbceee..69f3ac5239 100644 --- a/src/modules/Search/SearchResult.js +++ b/src/modules/Search/SearchResult.js @@ -1,6 +1,7 @@ import cx from 'clsx' +import _ from 'lodash' import PropTypes from 'prop-types' -import React, { Component } from 'react' +import React from 'react' import { createHTMLImage, @@ -30,32 +31,29 @@ const defaultRenderer = ({ image, price, title, description }) => [ , ] -export default class SearchResult extends Component { - handleClick = (e) => { - const { onClick } = this.props +const SearchResult = React.forwardRef(function (props, ref) { + const { active, className, renderer } = props - if (onClick) onClick(e, this.props) + const handleClick = (e) => { + _.invoke(props, 'onClick', e, props) } - render() { - const { active, className, renderer } = this.props - - const classes = cx(useKeyOnly(active, 'active'), 'result', className) - const rest = getUnhandledProps(SearchResult, this.props) - const ElementType = getElementType(SearchResult, this.props) - - // Note: You technically only need the 'content' wrapper when there's an - // image. However, optionally wrapping it makes this function a lot more - // complicated and harder to read. Since always wrapping it doesn't affect - // the style in any way let's just do that. - return ( - - {renderer(this.props)} - - ) - } -} - + const classes = cx(useKeyOnly(active, 'active'), 'result', className) + const rest = getUnhandledProps(SearchResult, props) + const ElementType = getElementType(SearchResult, props) + + // Note: You technically only need the 'content' wrapper when there's an + // image. However, optionally wrapping it makes this function a lot more + // complicated and harder to read. Since always wrapping it doesn't affect + // the style in any way let's just do that. + return ( + + {renderer(props)} + + ) +}) + +SearchResult.displayName = 'SearchResult' SearchResult.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, @@ -104,3 +102,5 @@ SearchResult.propTypes = { SearchResult.defaultProps = { renderer: defaultRenderer, } + +export default SearchResult diff --git a/src/modules/Search/SearchResults.js b/src/modules/Search/SearchResults.js index 1d277d4f2b..dc39226950 100644 --- a/src/modules/Search/SearchResults.js +++ b/src/modules/Search/SearchResults.js @@ -4,19 +4,20 @@ import React from 'react' import { childrenUtils, customPropTypes, getElementType, getUnhandledProps } from '../../lib' -function SearchResults(props) { +const SearchResults = React.forwardRef(function (props, ref) { const { children, className, content } = props const classes = cx('results transition', className) const rest = getUnhandledProps(SearchResults, props) const ElementType = getElementType(SearchResults, props) return ( - + {childrenUtils.isNil(children) ? content : children} ) -} +}) +SearchResults.displayName = 'SearchResults' SearchResults.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/test/specs/modules/Search/SearchCategory-test.js b/test/specs/modules/Search/SearchCategory-test.js index 129f1c634a..063e2b89c9 100644 --- a/test/specs/modules/Search/SearchCategory-test.js +++ b/test/specs/modules/Search/SearchCategory-test.js @@ -5,6 +5,7 @@ import * as common from 'test/specs/commonTests' describe('SearchCategory', () => { common.isConformant(SearchCategory) + common.forwardsRef(SearchCategory) common.rendersChildren(SearchCategory) describe('children', () => { diff --git a/test/specs/modules/Search/SearchCategoryLayout-test.js b/test/specs/modules/Search/SearchCategoryLayout-test.js new file mode 100644 index 0000000000..e904ea00dd --- /dev/null +++ b/test/specs/modules/Search/SearchCategoryLayout-test.js @@ -0,0 +1,13 @@ +import * as React from 'react' + +import SearchCategoryLayout from 'src/modules/Search/SearchCategoryLayout' +import * as common from 'test/specs/commonTests' + +const requiredProps = { + categoryContent:
, + resultsContent:
, +} + +describe('SearchCategoryLayout', () => { + common.isConformant(SearchCategoryLayout, { requiredProps, rendersChildren: false }) +}) diff --git a/test/specs/modules/Search/SearchResult-test.js b/test/specs/modules/Search/SearchResult-test.js index 2daf7f5f17..5a70631f75 100644 --- a/test/specs/modules/Search/SearchResult-test.js +++ b/test/specs/modules/Search/SearchResult-test.js @@ -1,9 +1,23 @@ +import React from 'react' + import SearchResult from 'src/modules/Search/SearchResult' import * as common from 'test/specs/commonTests' +import { sandbox } from 'test/utils' const requiredProps = { title: '' } describe('SearchResult', () => { common.isConformant(SearchResult, { requiredProps }) + common.forwardsRef(SearchResult, { requiredProps }) common.propKeyOnlyToClassName(SearchResult, 'active', { requiredProps }) + + describe('onClick', () => { + it('is called with (e, data) when clicked', () => { + const onClick = sandbox.spy() + mount().simulate('click') + + onClick.should.have.been.calledOnce() + onClick.should.have.been.calledWithMatch({ type: 'click' }, requiredProps) + }) + }) }) diff --git a/test/specs/modules/Search/SearchResults-test.js b/test/specs/modules/Search/SearchResults-test.js index 5b53f10f83..c86c31b68f 100644 --- a/test/specs/modules/Search/SearchResults-test.js +++ b/test/specs/modules/Search/SearchResults-test.js @@ -3,5 +3,6 @@ import * as common from 'test/specs/commonTests' describe('SearchResults', () => { common.isConformant(SearchResults) + common.forwardsRef(SearchResults) common.rendersChildren(SearchResults) })