From 5a07d7ca7fcd0bce6d10038b3e12f0cea360e0a4 Mon Sep 17 00:00:00 2001 From: Braulio Diez Botella Date: Fri, 11 Nov 2022 09:06:30 +0100 Subject: [PATCH 1/3] Removed HOC --- src/index.d.ts | 114 +++----- src/index.js | 15 +- src/trackerHoc.js | 80 ------ src/trackerHoc.test.js | 632 ----------------------------------------- 4 files changed, 54 insertions(+), 787 deletions(-) delete mode 100644 src/trackerHoc.js delete mode 100644 src/trackerHoc.test.js diff --git a/src/index.d.ts b/src/index.d.ts index f92413e..1b297c9 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -1,67 +1,47 @@ -// Type definitions for react-promise-tracker -// Project: https://github.com/Lemoncode/react-promise-tracker -// Definitions by: Lemoncode - -import * as React from "react"; - -/** - * It tracks a promise while in pending state. - * @param promise Input promise to be tracked. - * @returns It returns the same promise as input. - */ -export function trackPromise(promise: Promise, area?: string): Promise; - -/** - * Perform a reset for the area counter (default-area by default). - */ -export function manuallyResetPromiseCounter(area?: string): void; - -/** - * Decrement the area counter (default-area by default). - */ -export function manuallyDecrementPromiseCounter(area?: string): void; - -/** - * Increment the area counter (default-area by default). - */ -export function manuallyIncrementPromiseCounter(area?: string): void; - -/** - * Configuration contract: user can setup areas (display more than one spinner) or delay when - * the spinner is shown (this is useful when a user has a fast connection, to avoid unneccessary flickering) - */ - -interface Config { - area?: string; - delay?: number; -} - -/** - * It wraps a given React component into a new component that adds properties to watch - * pending promises (HOC). - * @param component Input component to be wrapped. - * @returns It returns a new component that extends the input one. - */ - -export interface ComponentToWrapProps { - config: Config; - promiseInProgress: boolean; -} - -export interface TrackerHocProps { - config?: Config; -} - -export function promiseTrackerHoc

( - component: React.ComponentType

-): React.ComponentType

; - -/** - * React Promise Tracker custom hook, this hook will expose a promiseInProgress boolean flag. - * - * @param configuration (optional can be null). - * @returns promiseInProgressFlag. - */ -export function usePromiseTracker( - outerConfig?: Config -): { promiseInProgress: boolean }; +// Type definitions for react-promise-tracker +// Project: https://github.com/Lemoncode/react-promise-tracker +// Definitions by: Lemoncode + +import * as React from "react"; + +/** + * It tracks a promise while in pending state. + * @param promise Input promise to be tracked. + * @returns It returns the same promise as input. + */ +export function trackPromise(promise: Promise, area?: string): Promise; + +/** + * Perform a reset for the area counter (default-area by default). + */ +export function manuallyResetPromiseCounter(area?: string): void; + +/** + * Decrement the area counter (default-area by default). + */ +export function manuallyDecrementPromiseCounter(area?: string): void; + +/** + * Increment the area counter (default-area by default). + */ +export function manuallyIncrementPromiseCounter(area?: string): void; + +/** + * Configuration contract: user can setup areas (display more than one spinner) or delay when + * the spinner is shown (this is useful when a user has a fast connection, to avoid unneccessary flickering) + */ + +interface Config { + area?: string; + delay?: number; +} + +/** + * React Promise Tracker custom hook, this hook will expose a promiseInProgress boolean flag. + * + * @param configuration (optional can be null). + * @returns promiseInProgressFlag. + */ +export function usePromiseTracker( + outerConfig?: Config +): { promiseInProgress: boolean }; diff --git a/src/index.js b/src/index.js index bc4a301..ccb14e9 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,7 @@ -export { - trackPromise, - manuallyResetPromiseCounter, - manuallyDecrementPromiseCounter, - manuallyIncrementPromiseCounter, -} from './trackPromise'; -export { promiseTrackerHoc } from './trackerHoc'; -export { usePromiseTracker } from './trackerHook'; +export { + trackPromise, + manuallyResetPromiseCounter, + manuallyDecrementPromiseCounter, + manuallyIncrementPromiseCounter, +} from './trackPromise'; +export { usePromiseTracker } from './trackerHook'; diff --git a/src/trackerHoc.js b/src/trackerHoc.js deleted file mode 100644 index 0066ab9..0000000 --- a/src/trackerHoc.js +++ /dev/null @@ -1,80 +0,0 @@ -import React, { Component } from 'react'; -import { - emitter, - getCounter, - promiseCounterUpdateEventId, -} from './trackPromise'; -import { setupConfig } from './setupConfig'; - -// Props: -// config: { -// area: // can be null|undefined|'' (will default to DefaultArea) or area name -// delay: // Wait Xms to display the spinner (fast connections scenario avoid blinking) -// default value 0ms -// } -export const promiseTrackerHoc = ComponentToWrap => { - return class promiseTrackerComponent extends Component { - constructor(props) { - super(props); - - this.state = { - promiseInProgress: false, - internalPromiseInProgress: false, - config: setupConfig(props.config), - }; - - this.notifyPromiseInProgress = this.notifyPromiseInProgress.bind(this); - this.updateProgress = this.updateProgress.bind(this); - this.subscribeToCounterUpdate = this.subscribeToCounterUpdate.bind(this); - } - - notifyPromiseInProgress() { - this.state.config.delay === 0 - ? this.setState({ promiseInProgress: true }) - : setTimeout(() => { - const progress = Boolean(getCounter(this.state.config.area) > 0); - this.setState({ promiseInProgress: progress }); - }, this.state.config.delay); - } - - updateProgress(progress, afterUpdateCallback) { - this.setState( - { internalPromiseInProgress: progress }, - afterUpdateCallback - ); - - !progress - ? this.setState({ promiseInProgress: false }) - : this.notifyPromiseInProgress(); - } - - subscribeToCounterUpdate() { - emitter.on(promiseCounterUpdateEventId, (anyPromiseInProgress, area) => { - if (this.state.config.area === area) { - this.updateProgress(anyPromiseInProgress); - } - }); - } - - componentDidMount() { - this.updateProgress( - Boolean(getCounter(this.state.config.area) > 0), - this.subscribeToCounterUpdate - ); - } - - componentWillUnmount() { - emitter.off(promiseCounterUpdateEventId); - } - - render() { - return ( - - ); - } - }; -}; diff --git a/src/trackerHoc.test.js b/src/trackerHoc.test.js deleted file mode 100644 index c565660..0000000 --- a/src/trackerHoc.test.js +++ /dev/null @@ -1,632 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import { promiseTrackerHoc } from './trackerHoc'; -import * as trackPromiseAPI from './trackPromise'; -import { defaultArea } from './constants'; - -const TestSpinnerComponent = (props) => ( -

props: {JSON.stringify(props, null, 4)}
-); - -describe('trackerHoc', () => { - describe('Initial Status', () => { - it('should render component with trackedPromiseInProgress equals false and area equals "default-area" when render promiseTrackerHoc without props', () => { - // Arrange - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false, area equals "default-area" and customProp equals "test" when feeding customProp equals "test"', () => { - // Arrange - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false and area equals "testArea" when feeding area equals "testArea"', () => { - // Arrange - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 0', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(0); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals false', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(0); - - const progress = false; - const area = defaultArea; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals false to different area', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(0); - - const progress = false; - const area = 'otherArea'; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals true when counter is 0 and emit event with progress equals true', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(0); - - const progress = true; - const area = defaultArea; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals true to different area', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(0); - - const progress = true; - const area = 'otherArea'; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals true when counter is 1', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(1); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals true when counter is 1 and emit event with progress equals true', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(1); - - const progress = true; - const area = defaultArea; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals true when counter is 1 and emit event with progress equals true to different area', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(1); - - const progress = true; - const area = 'otherArea'; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 1 and emit event with progress equals false', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(1); - - const progress = false; - const area = defaultArea; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals true when counter is 1 and emit event with progress equals false to different area', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(1); - - const progress = false; - const area = 'otherArea'; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render(); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false and area equals "testArea" when feeding area equals "testArea" and delay equals 300', () => { - // Arrange - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 0 and delay equals 300', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(0); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals false and delay equals 300', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(0); - - const progress = false; - const area = defaultArea; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals false to different area and delay equals 300', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(0); - - const progress = false; - const area = 'otherArea'; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals true when counter is 0 and emit event with progress equals true and delay equals 300', () => { - // Arrange - trackPromiseAPI.getCounter = jest - .fn() - .mockReturnValueOnce(0) - .mockReturnValueOnce(1); - - const progress = true; - const area = defaultArea; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - const setTimeoutStub = jest - .spyOn(window, 'setTimeout') - .mockImplementation((callback) => callback()); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals true to different area and delay equals 300', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(0); - - const progress = true; - const area = 'otherArea'; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 1 and delay equals 300', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(1); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 1 and emit event with progress equals true and delay equals 300', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(1); - - const progress = true; - const area = defaultArea; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 1 and emit event with progress equals true to different area and delay equals 300', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(1); - - const progress = true; - const area = 'otherArea'; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 1 and emit event with progress equals false and delay equals 300', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(1); - - const progress = false; - const area = defaultArea; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - - it('should render component with trackedPromiseInProgress equals false when counter is 1 and emit event with progress equals false to different area and delay equals 300', () => { - // Arrange - trackPromiseAPI.getCounter = jest.fn().mockReturnValue(1); - - const progress = false; - const area = 'otherArea'; - const emitterStub = jest - .spyOn(trackPromiseAPI.emitter, 'on') - .mockImplementation((id, callback) => callback(progress, area)); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - - // Assert - const { asFragment } = render( - - ); - - expect(trackPromiseAPI.getCounter).toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); - }); - }); - - describe('Handling delay timeouts', () => { - beforeEach(() => { - jest.useFakeTimers(); - }); - - afterAll(() => { - jest.useRealTimers(); - }); - - it('should render

NO SPINNER

when counter is 1 but delay is set to 300 (before timing out)', async () => { - // Arrange - const TestSpinnerComponent = (props) => { - return ( -
- {props.promiseInProgress ?

SPINNER

:

NO SPINNER

} -
- ); - }; - - const getCounterStub = jest.spyOn(trackPromiseAPI, 'getCounter'); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - render(); - - // Check very beginning (no promises going on) NO SPINNER is shown - // TODO: this assert could be skipped (move to another test) - expect(screen.getByText('NO SPINNER')).toBeInTheDocument(); - expect(getCounterStub).toHaveBeenCalled(); - - // Assert - // This promise will resolved after 1 seconds, by doing this - // we will be able to test 2 scenarios: - // [0] first 200ms spinner won't be shown (text NOSPINNER) - // [1] after 200ms spinner will be shown (text SPINNER) - // [2] after 1000ms spinner will be hidded again (text NOSPINNER) - - const myFakePromise = new Promise((resolve) => { - setTimeout(() => { - resolve(true); - }, 1000); - }); - - trackPromiseAPI.trackPromise(myFakePromise); - - jest.advanceTimersByTime(100); - - // [0] first 200ms spinner won't be shown (text NOSPINNER) - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - - jest.advanceTimersByTime(300); - - // Before the promise get's resolved - // [1] after 200ms spinner will be shown (text SPINNER) - expect(await screen.findByText('SPINNER')).toBeInTheDocument(); - - // After the promise get's resolved - jest.runAllTimers(); - - // [2] after 1000ms spinner will be hidded again (text NOSPINNER) - // Wait for fakePromise (simulated ajax call) to be completed - // no spinner should be shown - - await myFakePromise; - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - expect(screen.queryByText('SPINNER')).not.toBeInTheDocument(); - }); - - it('should render

SPINNER

when counter is 1, delay is set to 1000 and promise has 2000 timeout', async () => { - // Arrange - const TestSpinnerComponent = (props) => { - return ( -
- {props.promiseInProgress ?

SPINNER

:

NO SPINNER

} -
- ); - }; - - const getCounterStub = jest.spyOn(trackPromiseAPI, 'getCounter'); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - render(); - - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - expect(getCounterStub).toHaveBeenCalled(); - - // Assert - const myFakePromise = new Promise((resolve) => { - setTimeout(() => { - resolve(true); - }, 2000); - }); - - trackPromiseAPI.trackPromise(myFakePromise); - - jest.advanceTimersByTime(500); - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - - // Total advance 1000 - jest.advanceTimersByTime(500); - expect(await screen.findByText('SPINNER')).toBeInTheDocument(); - - // Total advance 1999 - jest.advanceTimersByTime(999); - expect(await screen.findByText('SPINNER')).toBeInTheDocument(); - - // After the promise get's resolved - jest.runAllTimers(); - - await myFakePromise; - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - - // Total advance 2010 - jest.advanceTimersByTime(11); - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - }); - - it('should render

NO SPINNER

when counter is 1, delay is set to 2000 and promise has 1000 timeout', async () => { - // Arrange - const TestSpinnerComponent = (props) => { - return ( -
- {props.promiseInProgress ?

SPINNER

:

NO SPINNER

} -
- ); - }; - - const getCounterStub = jest.spyOn(trackPromiseAPI, 'getCounter'); - - // Act - const TrackedComponent = promiseTrackerHoc(TestSpinnerComponent); - render(); - - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - expect(getCounterStub).toHaveBeenCalled(); - - // Assert - const myFakePromise = new Promise((resolve) => { - setTimeout(() => { - resolve(true); - }, 1000); - }); - - trackPromiseAPI.trackPromise(myFakePromise); - - jest.advanceTimersByTime(500); - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - - // Total advance 1000 - jest.advanceTimersByTime(500); - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - - await myFakePromise; - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - - // Total advance 1999 - jest.advanceTimersByTime(999); - expect(await screen.findByText('NO SPINNER')).toBeInTheDocument(); - - // After the promise get's resolved - jest.runAllTimers(); - }); - }); -}); From 1a29689f97395473befcbe500bcdaf1de6757cd4 Mon Sep 17 00:00:00 2001 From: Braulio Diez Botella Date: Fri, 11 Nov 2022 09:34:33 +0100 Subject: [PATCH 2/3] updated readme and removed hoc snapshot --- readme.md | 424 +++++++++++----------- src/__snapshots__/trackerHoc.test.js.snap | 338 ----------------- 2 files changed, 216 insertions(+), 546 deletions(-) delete mode 100644 src/__snapshots__/trackerHoc.test.js.snap diff --git a/readme.md b/readme.md index c726d74..e9a25b4 100644 --- a/readme.md +++ b/readme.md @@ -1,208 +1,216 @@ -[![Build Status](https://github.com/Lemoncode/react-promise-tracker/actions/workflows/ci.yml/badge.svg)](https://github.com/Lemoncode/react-promise-tracker/actions/workflows/ci.yml) - -# react-promise-tracker - -Simple promise tracker React Hoc. You can see it in action in this [Live Demo](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/00-example-basic), and find the basic info to get started in this [post](https://www.basefactor.com/react-how-to-display-a-loading-indicator-on-fetch-calls). - -For detailed information check out the [documentation](https://lemoncode.github.io/react-promise-tracker/) - -# Why do I need this? - -Sometimes we need to track blocking promises (e.g. fetch or axios http calls), and control whether to -display a loading spinner indicator not, you have to take care of scenarios like: - -- You could need to track several ajax calls being performed in parallel. -- Some of them you want to be tracked some others to be executed silently in background. -- You may want to have several spinners blocking only certain areas of the screen. -- For high speed connection you may want to show the loading spinner after an small delay of time - to avoid having a flickering effect in your screen. - -This library implements: - -- A simple function that will allow a promise to be tracked. -- A Hook + HOC component that will allow us wrap a loading spinner (it will be displayed when the number of tracked request are greater than zero, and hidden when not). - -# Installation - -```cmd -npm install react-promise-tracker --save -``` - -# Usage - -Whenever you want a promise to be tracked, just wrap it like in the code below: - -```diff -+ import { trackPromise} from 'react-promise-tracker'; -//... - -+ trackPromise( - fetchUsers(); // You function that returns a promise -+ ); -``` - -Then you only need to create a spinner component and make use of the _usePromiseTracker_, this -hook will expose a boolean property that will let us decide whether to show or hide the loading -spinner. - -## Basic sample: - -```diff -import React, { Component } from 'react'; -+ import { usePromiseTracker } from "react-promise-tracker"; - -export const LoadingSpinerComponent = (props) => { -+ const { promiseInProgress } = usePromiseTracker(); - - return ( -
- { -+ (promiseInProgress === true) ? -

Hey I'm a spinner loader wannabe !!!

- : - null - } -
- ) -}; -``` - -- To add a cool spinner component you can make use of _react-spinners_: - - - [Demo page](http://www.davidhu.io/react-spinners/) - - [Github page](https://github.com/davidhu2000/react-spinners) - -* Then in your application entry point (main / app / ...) just add this loading spinner to be displayed: - -```diff -import React from 'react'; -+ import { LoadingSpinnerComponent} from './loadingSpinner'; - -export const AppComponent = (props) => ( -
-

Hello App!

-+ -
-); -``` - -## Sample with areas: - -Using react-promise-tracker as is will just display a single spinner in your page, there are cases where you want to display a given spinner only blocking certain area of the screen (e.g.: a product list app with a shopping cart section. -We would like to block the ui (show spinner) while is loading the product, but not the rest of the user interface, and the same thing with the shopping cart pop-up section. - -![Shopping cart sample](/resources/00-shopping-cart-sample.png) - -The _promiseTracker_ hooks exposes a config parameter, here we can define the area that we want to setup -(by default o area). We could just feed the area in the props of the common spinner we have created - -```diff -export const Spinner = (props) => { -+ const { promiseInProgress } = usePromiseTracker({area: props.area}); - - return ( - promiseInProgress && ( -
- -
- ) - ); -}; -``` - -We could add the `default-area` to show product list spinner (no params means just default area): - -```diff -import React from 'react'; -+ import { LoadingSpinnerComponent} from './loadingSpinner'; - -export const ProductListComponent = (props) => ( -
- ... -+ // default-area -
-); -``` - -And we add the `shopping-cart-area` to show shopping cart spinner: - -```diff -import React from 'react'; -+ import { LoadingSpinnerComponent} from './loadingSpinner'; - -export const ShoppingCartModal = (props) => ( -
-+ -
-); -``` - -The when we track a given promise we can choose the area that would be impacted. - -```diff -+ import { trackPromise} from 'react-promise-tracker'; -... -+ trackPromise( - fetchSelectedProducts(); -+ ,'shopping-cart-area'); -``` - -## Sample with delay: - -You can add as well a delay to display the spinner, When is this useful? if your users are connected on -high speed connections it would be worth to show the spinner right after 500 Ms (checking that the -ajax request hasn't been completed), this will avoid having undesired screen flickering on high speed -connection scenarios. - -```diff -export const Spinner = (props) => { -+ const { promiseInProgress } = usePromiseTracker({delay: 500}); -``` - -# Demos - -Full examples: - -> NOTE: If you are going to modify the following examples in Codesandbox, you must first do a fork - -- **00 Basic Example**: minimum sample to get started. - - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/00-example-basic) - - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/00-example-basic) - -- **01 Example Areas**: defining more than one spinner to be displayed in separate screen areas. - - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/01-example-areas) - - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/01-example-areas) - -- **02 Example Delay**: displaying the spinner after some miliseconds delay (useful when your users havbe high speed connections). - - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/02-example-delay) - - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/02-example-delay) - -- **03 Example Hoc**: using legacy high order component approach (useful if your spinner is a class based component). - - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/03-example-hoc) - - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/03-example-hoc) - -- **04 Initial load**: launching ajax request just on application startup before the spinner is being mounted. - - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/04-initial-load) - - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/04-initial-load) - -- **05 Typescript**: full sample using typescript (using library embedded typings). - - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/05-typescript) - - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/05-typescript) - -- **06 Suspense Like**: sample implementing a suspense-like component (typescript). - - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/06-suspense-like) - - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/06-suspense-like) - -- **07 Suspense Custom**: sample implementing a suspense-like component that can be customized by passing a spinner component of your choice (typescript). - - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/07-suspense-custom) - - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/07-suspense-custom) - -# About Basefactor + Lemoncode - -We are an innovating team of Javascript experts, passionate about turning your ideas into robust products. - -[Basefactor, consultancy by Lemoncode](http://www.basefactor.com) provides consultancy and coaching services. - -[Lemoncode](http://lemoncode.net/services/en/#en-home) provides training services. - -For the LATAM/Spanish audience we are running an Online Front End Master degree, more info: http://lemoncode.net/master-frontend +[![Build Status](https://github.com/Lemoncode/react-promise-tracker/actions/workflows/ci.yml/badge.svg)](https://github.com/Lemoncode/react-promise-tracker/actions/workflows/ci.yml) + +# react-promise-tracker + +Simple promise tracker React Hook. You can see it in action in this [Live Demo](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/00-example-basic), and find the basic info to get started in this [post](https://www.basefactor.com/react-how-to-display-a-loading-indicator-on-fetch-calls). + +For detailed information check out the [documentation](https://lemoncode.github.io/react-promise-tracker/) + +# Why do I need this? + +Sometimes we need to track blocking promises (e.g. fetch or axios http calls), and control whether to +display a loading spinner indicator not, you have to take care of scenarios like: + +- You could need to track several ajax calls being performed in parallel. +- Some of them you want to be tracked some others to be executed silently in background. +- You may want to have several spinners blocking only certain areas of the screen. +- For high speed connection you may want to show the loading spinner after an small delay of time + to avoid having a flickering effect in your screen. + +This library implements: + +- A simple function that will allow a promise to be tracked. +- A Hook that will allow us wrap a loading spinner (it will be displayed when the number of tracked request are greater than zero, and hidden when not). + +> Note HOC version of the library has been removed in version 3.0, if you want to use it, please use a version prior to 3.0. + +# Installation + +```cmd +npm install react-promise-tracker --save +``` + +# Usage + +Whenever you want a promise to be tracked, just wrap it like in the code below: + +```diff ++ import { trackPromise} from 'react-promise-tracker'; +//... + ++ trackPromise( + fetchUsers(); // You function that returns a promise ++ ); +``` + +Then you only need to create a spinner component and make use of the _usePromiseTracker_, this +hook will expose a boolean property that will let us decide whether to show or hide the loading +spinner. + +## Basic sample: + +```diff +import React, { Component } from 'react'; ++ import { usePromiseTracker } from "react-promise-tracker"; + +export const LoadingSpinerComponent = (props) => { ++ const { promiseInProgress } = usePromiseTracker(); + + return ( +
+ { ++ (promiseInProgress === true) ? +

Hey I'm a spinner loader wannabe !!!

+ : + null + } +
+ ) +}; +``` + +- To add a cool spinner component you can make use of _react-spinners_: + + - [Demo page](http://www.davidhu.io/react-spinners/) + - [Github page](https://github.com/davidhu2000/react-spinners) + +* Then in your application entry point (main / app / ...) just add this loading spinner to be displayed: + +```diff +import React from 'react'; ++ import { LoadingSpinnerComponent} from './loadingSpinner'; + +export const AppComponent = (props) => ( +
+

Hello App!

++ +
+); +``` + +## Sample with areas: + +Using react-promise-tracker as is will just display a single spinner in your page, there are cases where you want to display a given spinner only blocking certain area of the screen (e.g.: a product list app with a shopping cart section. +We would like to block the ui (show spinner) while is loading the product, but not the rest of the user interface, and the same thing with the shopping cart pop-up section. + +![Shopping cart sample](/resources/00-shopping-cart-sample.png) + +The _promiseTracker_ hooks exposes a config parameter, here we can define the area that we want to setup +(by default o area). We could just feed the area in the props of the common spinner we have created + +```diff +export const Spinner = (props) => { ++ const { promiseInProgress } = usePromiseTracker({area: props.area}); + + return ( + promiseInProgress && ( +
+ +
+ ) + ); +}; +``` + +We could add the `default-area` to show product list spinner (no params means just default area): + +```diff +import React from 'react'; ++ import { LoadingSpinnerComponent} from './loadingSpinner'; + +export const ProductListComponent = (props) => ( +
+ ... ++ // default-area +
+); +``` + +And we add the `shopping-cart-area` to show shopping cart spinner: + +```diff +import React from 'react'; ++ import { LoadingSpinnerComponent} from './loadingSpinner'; + +export const ShoppingCartModal = (props) => ( +
++ +
+); +``` + +The when we track a given promise we can choose the area that would be impacted. + +```diff ++ import { trackPromise} from 'react-promise-tracker'; +... ++ trackPromise( + fetchSelectedProducts(); ++ ,'shopping-cart-area'); +``` + +## Sample with delay: + +You can add as well a delay to display the spinner, When is this useful? if your users are connected on +high speed connections it would be worth to show the spinner right after 500 Ms (checking that the +ajax request hasn't been completed), this will avoid having undesired screen flickering on high speed +connection scenarios. + +```diff +export const Spinner = (props) => { ++ const { promiseInProgress } = usePromiseTracker({delay: 500}); +``` + +# Demos + +Full examples: + +> NOTE: If you are going to modify the following examples in Codesandbox, you must first do a fork + +- **00 Basic Example**: minimum sample to get started. + - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/00-example-basic) + - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/00-example-basic) + +- **01 Example Areas**: defining more than one spinner to be displayed in separate screen areas. + - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/01-example-areas) + - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/01-example-areas) + +- **02 Example Delay**: displaying the spinner after some miliseconds delay (useful when your users havbe high speed connections). + - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/02-example-delay) + - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/02-example-delay) + + +- **04 Initial load**: launching ajax request just on application startup before the spinner is being mounted. + - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/04-initial-load) + - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/04-initial-load) + +- **05 Typescript**: full sample using typescript (using library embedded typings). + - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/05-typescript) + - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/05-typescript) + +- **06 Suspense Like**: sample implementing a suspense-like component (typescript). + - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/06-suspense-like) + - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/06-suspense-like) + +- **07 Suspense Custom**: sample implementing a suspense-like component that can be customized by passing a spinner component of your choice (typescript). + - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/07-suspense-custom) + - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/07-suspense-custom) + +# Legacy + +If need to use an HOC solution because your codebase is legacy, you can refer to the following examples (version prior to 3.0). + +- **03 Example Hoc**: using legacy high order component approach (useful if your spinner is a class based component). + - [Stackblitz](https://stackblitz.com/github/lemoncode/react-promise-tracker/tree/master/examples/03-example-hoc) + - [Codesandbox](https://codesandbox.io/s/github/lemoncode/react-promise-tracker/tree/master/examples/03-example-hoc) + + +# About Basefactor + Lemoncode + +We are an innovating team of Javascript experts, passionate about turning your ideas into robust products. + +[Basefactor, consultancy by Lemoncode](http://www.basefactor.com) provides consultancy and coaching services. + +[Lemoncode](http://lemoncode.net/services/en/#en-home) provides training services. + +For the LATAM/Spanish audience we are running an Online Front End Master degree, more info: http://lemoncode.net/master-frontend diff --git a/src/__snapshots__/trackerHoc.test.js.snap b/src/__snapshots__/trackerHoc.test.js.snap deleted file mode 100644 index f607585..0000000 --- a/src/__snapshots__/trackerHoc.test.js.snap +++ /dev/null @@ -1,338 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false and area equals "default-area" when render promiseTrackerHoc without props 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false and area equals "testArea" when feeding area equals "testArea" 1`] = ` - -
-    props: {
-    "config": {
-        "area": "testArea",
-        "delay": 0
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false and area equals "testArea" when feeding area equals "testArea" and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "testArea",
-        "delay": 300
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 0 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 0 and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 300
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals false 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals false and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 300
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals false to different area 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals false to different area and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 300
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals true to different area 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 0 and emit event with progress equals true to different area and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 300
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 1 and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 300
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 1 and emit event with progress equals false 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 1 and emit event with progress equals false and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 300
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 1 and emit event with progress equals false to different area and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 300
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 1 and emit event with progress equals true and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 300
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false when counter is 1 and emit event with progress equals true to different area and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 300
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals false, area equals "default-area" and customProp equals "test" when feeding customProp equals "test" 1`] = ` - -
-    props: {
-    "customProp": "test",
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": false
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals true when counter is 0 and emit event with progress equals true 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": true
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals true when counter is 0 and emit event with progress equals true and delay equals 300 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 300
-    },
-    "promiseInProgress": true
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals true when counter is 1 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": true
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals true when counter is 1 and emit event with progress equals false to different area 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": true
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals true when counter is 1 and emit event with progress equals true 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": true
-}
-  
-
-`; - -exports[`trackerHoc Initial Status should render component with trackedPromiseInProgress equals true when counter is 1 and emit event with progress equals true to different area 1`] = ` - -
-    props: {
-    "config": {
-        "area": "default-area",
-        "delay": 0
-    },
-    "promiseInProgress": true
-}
-  
-
-`; From 6c23182305e1245103e18253a9bb7e4bb39231d6 Mon Sep 17 00:00:00 2001 From: Braulio Diez Botella Date: Fri, 11 Nov 2022 12:50:59 +0100 Subject: [PATCH 3/3] updated readme es --- readme_es.md | 288 ++++++++++++++++++++++++++------------------------- 1 file changed, 146 insertions(+), 142 deletions(-) diff --git a/readme_es.md b/readme_es.md index 1e0dbae..ba8dc76 100644 --- a/readme_es.md +++ b/readme_es.md @@ -1,142 +1,146 @@ -# react-promise-tracker - -Componente React Hoc, rastreador de promesas. - Puedes verlo en acción: [Demo](https://stackblitz.com/edit/react-promise-tracker-default-area-sample) - -## ¿Por qué necesito esto? - -Algunas veces necesitas rastrear promesas bloqueantes (ejemplo: fetch http calls), -para escoger entre mostrar un spinner de cargando... o no. - -Esta librería implementa: - -- Una función simple que te permitirá rastrear una promesa. -- Un componente HOC, que nos permitirá usar un wrapper como spinner de cargando... (se mostrará cuando el número de peticiones rastreadas sea mayor que cero, y estará oculto cuando no). - -## Instalación - -```cmd -npm install react-promise-tracker --save -``` - -## Uso - -Siempre que quieras rastrear una promesa, simplemente usa el componente como wrapper tal como se muestra en el siguiente código: - -```diff -+ import { trackPromise} from 'react-promise-tracker'; -//... - -+ trackPromise( - fetchUsers(); // You function that returns a promise -+ ); -``` - -Entonces solo necesitas crear el componente que define una propiedad llamada _trackedPromiseInProgress_ - -Y envolverlo con el _promiseTrackerHoc_ - -## Ejemplo básico - -```diff -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -+ import { promiseTrackerHoc} from 'react-promise-tracker'; - -const InnerLoadingSpinerComponent = (props) => { - return ( -
- { - (props.trackedPromiseInProgress === true) ? -

Hey I'm a spinner loader wannabe !!!

- : - null - } -
- ) -}; - -InnerLoadingSpinerComponent.propTypes = { - trackedPromiseInProgress : PropTypes.bool.isRequired, -}; - -+ export const LoadingSpinnerComponent = promiseTrackerHoc(InnerLoadingSpinerComponent); -``` - -- Para añadir un component spinner atractivo, puedes hacer uso de _react-spinners_: - - - [Demo page](http://www.davidhu.io/react-spinners/) - - [Github page](https://github.com/davidhu2000/react-spinners) - -- Luego en el punto de entrada de tu apliación (main / app / ...) solo añade este componente loading spinner, para que sea renderizado: - -```diff -import React from 'react'; -+ import { LoadingSpinnerComponent} from './loadingSpinner'; - -export const AppComponent = (props) => ( -
-

Hello App!

-+ -
-); -``` - -## Ejemplo con áreas - -Es posible usar react-promise-tracker como si se mostrara un solo spinner en la página. Hay casos en los que desea mostrar un spinner solo bloqueando cierta área de la pantalla (por ejemplo, una aplicación de lista de productos con una sección de carrito de la compra). -Nos gustaría bloquear esa área de la UI (mostrar sólo el spinner) mientras carga el producto, pero no el resto de la interfaz de usuario, y lo mismo con la sección pop-up del carro de compras. - -![Shopping cart sample](./resources/00-shopping-cart-sample.png) - -Podemos añadir el área `default-area` para mostrar el spinner de la lista de productos: - -```diff -import React from 'react'; -+ import { LoadingSpinnerComponent} from './loadingSpinner'; - -export const ProductListComponent = (props) => ( -
- ... -+ // default-area -
-); -``` - -Si añadimos el área, `shopping-cart-area` mostraremos el spinner del carro de compra: - -```diff -import React from 'react'; -+ import { LoadingSpinnerComponent} from './loadingSpinner'; - -export const ShoppingCartModal = (props) => ( -
-+ -
-); -``` - -Con este enfoque, no necesitamos definir diferentes componentes spinners, con uno solo podemos renderizarlo cuando queramos rastrear promises en una determinada área: - -```diff -+ import { trackPromise} from 'react-promise-tracker'; -... -+ trackPromise( - fetchSelectedProducts(); -+ ,'shopping-cart-area'); -``` - -## Demos - -Si quieres verlo en acción puedes visitar: - -- [Ejemplo del área por defecto](https://stackblitz.com/edit/react-promise-tracker-default-area-sample) - -- [Ejemplo de dos áreas](https://stackblitz.com/edit/react-promise-tracker-two-areas-sample) - -## Sobre Lemoncode - -Somos un equipo de una larga experiencia como desarrolladores freelance, establecidos como grupo en 2010. -Estamos especializados en tecnologías Front End y .NET. [Click aquí](http://lemoncode.net/services/en/#en-home) para más info sobre nosotros. - -Para la audiencia LATAM/Español estamos desarrollando un máster Front End Online, más info: [http://lemoncode.net/master-frontend](http://lemoncode.net/master-frontend) +# react-promise-tracker + +Componente React Hoc, rastreador de promesas. + + +Para ver como funciona: [Demo](https://stackblitz.com/edit/react-promise-tracker-default-area-sample) + +## ¿Por qué necesito esto? + +Cuando realizamos llamadas AJAX (usando Fetch, Axios o cualquier tipo de librería...), resulta que ciertas llamadas son bloqueantes (es decir tenemos que evitar que el usuario pueda interactuar con la aplicación mientras se está realizando la llamada), y otras las hacemos en background (el usuario +puede seguir interactuando con la aplicación mientras se está realizando la llamada). + +Gestionar esto no es fácil, ya que dichas llamadas se pueden realizar a +diferentes niveles de la aplicación ¿Cómo podemos hacer para saber si +tenemos que mostrar un spinner de carga y bloquear el UI? React Promise +Tracker se encarga de gestionar ese estado por ti. + +Esta librería implementa: + +- Una función que te permitirá que la librería haga tracking de una promesa. +- Un componente HOC, que nos permitirá usar un wrapper para mostrar/ocultar un spinner que indique que se están cargando datos... (se mostrará cuando el número de peticiones rastreadas sea mayor que cero, y estará oculto cuando no). + +## Instalación + +```cmd +npm install react-promise-tracker --save +``` + +## Uso + +Siempre que quieras trackear una promesa, simplemente usa el componente como wrapper tal como se muestra en el siguiente código: + +```diff ++ import { trackPromise} from 'react-promise-tracker'; +//... + ++ trackPromise( + fetchUsers(); // You function that returns a promise ++ ); +``` + +Después sólo te hace falta crear el componente de spinner, usar el hook __ y +usar el flag de __ para saber si hay promesas bloqueantes en marcha o no: + +```diff +import React, { Component } from 'react'; ++ import { usePromiseTracker } from "react-promise-tracker"; + +export const LoadingSpinerComponent = (props) => { ++ const { promiseInProgress } = usePromiseTracker(); + + return ( +
+ { ++ (promiseInProgress === true) ? +

Hey I'm a spinner loader wannabe !!!

+ : + null + } +
+ ) +}; +``` + +- Para añadir un component spinner que un aspecto más profesional, puedes hacer uso de _react-spinners_: + + - [Demo page](http://www.davidhu.io/react-spinners/) + - [Github page](https://github.com/davidhu2000/react-spinners) + +- Luego en el punto de entrada de tu aplicación (main / app / ...) solo tienes +que añadir el componente de spinner para que se renderice cuando toque: + +```diff +import React from 'react'; ++ import { LoadingSpinnerComponent} from './loadingSpinner'; + +export const AppComponent = (props) => ( +
+

Hello App!

++ +
+); +``` + +## Ejemplo con áreas + +Hay veces en las que tener un sólo spinner para toda la aplicación no te vale, en ciertos escenarios puede querer hacer tracking por separado de varias zonas +de tu interfaz de usuario, para ello puedes hacer uso de las areas de esta +librería (por ejemplo, en una aplicación de lista de productos con una sección de carrito de la compra, igual quieres bloquear la lista de la compra pero no el +carrito). + +Vamos a definir dos areas, una para el carrito de la compra y otra para la lista de productos: + +![Shopping cart sample](./resources/00-shopping-cart-sample.png) + +Podemos añadir el área `default-area` para mostrar el spinner de la lista de productos: + +```diff +import React from 'react'; ++ import { LoadingSpinnerComponent} from './loadingSpinner'; + +export const ProductListComponent = (props) => ( +
+ ... ++ // default-area +
+); +``` + +Si añadimos el área, `shopping-cart-area` mostraremos el spinner del carro de compra: + +```diff +import React from 'react'; ++ import { LoadingSpinnerComponent} from './loadingSpinner'; + +export const ShoppingCartModal = (props) => ( +
++ +
+); +``` + +Con este enfoque, no necesitamos definir diferentes componentes spinners, con uno solo podemos renderizarlo cuando queramos rastrear promises en una determinada área: + +```diff ++ import { trackPromise} from 'react-promise-tracker'; +... ++ trackPromise( + fetchSelectedProducts(); ++ ,'shopping-cart-area'); +``` + +## Demos + +Si quieres verlo en acción puedes visitar: + +- [Ejemplo del área por defecto](https://stackblitz.com/edit/react-promise-tracker-default-area-sample) + +- [Ejemplo de dos áreas](https://stackblitz.com/edit/react-promise-tracker-two-areas-sample) + +## Sobre Lemoncode + +Somos un equipo de una larga experiencia como desarrolladores freelance, establecidos como grupo en 2010. +Estamos especializados en tecnologías Front End y .NET. [Click aquí](http://lemoncode.net/services/en/#en-home) para más info sobre nosotros. + +Para la audiencia LATAM/Español estamos desarrollando un máster Front End Online, más info: [http://lemoncode.net/master-frontend](http://lemoncode.net/master-frontend)