From f55d3a66aa4bfb2df3d7c7116888edb82d76c0a3 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 6 Mar 2020 21:44:03 +0100 Subject: [PATCH] Converted ShortUrlsRow component into a functional component --- src/short-urls/helpers/ShortUrlsRow.js | 72 +++++++++----------- src/short-urls/services/provideServices.js | 2 +- src/utils/services/provideServices.js | 3 +- src/utils/utils.js | 10 +++ test/short-urls/helpers/ShortUrlsRow.test.js | 13 +--- 5 files changed, 49 insertions(+), 51 deletions(-) diff --git a/src/short-urls/helpers/ShortUrlsRow.js b/src/short-urls/helpers/ShortUrlsRow.js index 0a2b66b6..a058a92a 100644 --- a/src/short-urls/helpers/ShortUrlsRow.js +++ b/src/short-urls/helpers/ShortUrlsRow.js @@ -13,40 +13,36 @@ import Tag from '../../tags/helpers/Tag'; import ShortUrlVisitsCount from './ShortUrlVisitsCount'; import './ShortUrlsRow.scss'; +const propTypes = { + refreshList: PropTypes.func, + shortUrlsListParams: shortUrlsListParamsType, + selectedServer: serverType, + shortUrl: shortUrlType, +}; + const ShortUrlsRow = ( ShortUrlsRowMenu, colorGenerator, - stateFlagTimeout -) => class ShortUrlsRow extends React.Component { - static propTypes = { - refreshList: PropTypes.func, - shortUrlsListParams: shortUrlsListParamsType, - selectedServer: serverType, - shortUrl: shortUrlType, - }; + useStateFlagTimeout +) => { + const ShortUrlsRowComp = ({ shortUrl, selectedServer, refreshList, shortUrlsListParams }) => { + const [ copiedToClipboard, setCopiedToClipboard ] = useStateFlagTimeout(false); + const renderTags = (tags) => { + if (isEmpty(tags)) { + return No tags; + } - state = { copiedToClipboard: false }; + const selectedTags = shortUrlsListParams.tags || []; - renderTags(tags) { - if (isEmpty(tags)) { - return No tags; - } - - const { refreshList, shortUrlsListParams } = this.props; - const selectedTags = shortUrlsListParams.tags || []; - - return tags.map((tag) => ( - refreshList({ tags: [ ...selectedTags, tag ] })} - /> - )); - } - - render() { - const { shortUrl, selectedServer } = this.props; + return tags.map((tag) => ( + refreshList({ tags: [ ...selectedTags, tag ] })} + /> + )); + }; return ( @@ -56,16 +52,10 @@ const ShortUrlsRow = ( - stateFlagTimeout(this.setState.bind(this), 'copiedToClipboard')} - > + - @@ -73,7 +63,7 @@ const ShortUrlsRow = ( - {this.renderTags(shortUrl.tags)} + {renderTags(shortUrl.tags)} ); - } + }; + + ShortUrlsRowComp.propTypes = propTypes; + + return ShortUrlsRowComp; }; export default ShortUrlsRow; diff --git a/src/short-urls/services/provideServices.js b/src/short-urls/services/provideServices.js index 014ecd74..3c3c258f 100644 --- a/src/short-urls/services/provideServices.js +++ b/src/short-urls/services/provideServices.js @@ -33,7 +33,7 @@ const provideServices = (bottle, connect) => { [ 'listShortUrls', 'resetShortUrlParams' ] )); - bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator', 'stateFlagTimeout'); + bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator', 'useStateFlagTimeout'); bottle.serviceFactory( 'ShortUrlsRowMenu', diff --git a/src/utils/services/provideServices.js b/src/utils/services/provideServices.js index 4c165f37..0efe06cd 100644 --- a/src/utils/services/provideServices.js +++ b/src/utils/services/provideServices.js @@ -1,5 +1,5 @@ import axios from 'axios'; -import { stateFlagTimeout } from '../utils'; +import { stateFlagTimeout, useStateFlagTimeout } from '../utils'; import Storage from './Storage'; import ColorGenerator from './ColorGenerator'; import buildShlinkApiClient from './ShlinkApiClientBuilder'; @@ -14,6 +14,7 @@ const provideServices = (bottle) => { bottle.constant('setTimeout', global.setTimeout); bottle.serviceFactory('stateFlagTimeout', stateFlagTimeout, 'setTimeout'); + bottle.serviceFactory('useStateFlagTimeout', useStateFlagTimeout, 'setTimeout'); }; export default provideServices; diff --git a/src/utils/utils.js b/src/utils/utils.js index d3118236..78d50daa 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -19,6 +19,16 @@ export const stateFlagTimeout = (setTimeout) => ( setTimeout(() => setState({ [flagName]: !initialValue }), delay); }; +export const useStateFlagTimeout = (setTimeout) => (initialValue = true, delay = DEFAULT_TIMEOUT_DELAY) => { + const [ flag, setFlag ] = useState(initialValue); + const callback = () => { + setFlag(!initialValue); + setTimeout(() => setFlag(initialValue), delay); + }; + + return [ flag, callback ]; +}; + export const determineOrderDir = (clickedField, currentOrderField, currentOrderDir) => { if (currentOrderField !== clickedField) { return 'ASC'; diff --git a/test/short-urls/helpers/ShortUrlsRow.test.js b/test/short-urls/helpers/ShortUrlsRow.test.js index dd12a39f..4c0d022c 100644 --- a/test/short-urls/helpers/ShortUrlsRow.test.js +++ b/test/short-urls/helpers/ShortUrlsRow.test.js @@ -12,7 +12,8 @@ describe('', () => { let wrapper; const mockFunction = () => ''; const ShortUrlsRowMenu = mockFunction; - const stateFlagTimeout = jest.fn(); + const stateFlagTimeout = jest.fn(() => true); + const useStateFlagTimeout = jest.fn(() => [ false, stateFlagTimeout ]); const colorGenerator = { getColorForKey: mockFunction, setColorForKey: mockFunction, @@ -30,7 +31,7 @@ describe('', () => { }; beforeEach(() => { - const ShortUrlsRow = createShortUrlsRow(ShortUrlsRowMenu, colorGenerator, stateFlagTimeout); + const ShortUrlsRow = createShortUrlsRow(ShortUrlsRowMenu, colorGenerator, useStateFlagTimeout); wrapper = shallow( @@ -96,12 +97,4 @@ describe('', () => { menu.simulate('copy'); expect(stateFlagTimeout).toHaveBeenCalledTimes(1); }); - - it('shows copy hint when state prop is true', () => { - const isHidden = () => wrapper.find('td').at(1).find('.short-urls-row__copy-hint').prop('hidden'); - - expect(isHidden()).toEqual(true); - wrapper.setState({ copiedToClipboard: true }); - expect(isHidden()).toEqual(false); - }); });