From a98d4e5c320134ad4441d75023c73f1ed400fc6f Mon Sep 17 00:00:00 2001 From: vishnu Date: Wed, 6 Nov 2024 15:44:19 +0530 Subject: [PATCH] reset quiz state when quiz id changes --- .../usePrevious/usePrevious.server.test.tsx | 19 ++++++++++ spec/hooks/usePrevious/usePrevious.test.tsx | 35 +++++++++++++++++++ src/hooks/usePrevious.ts | 14 ++++++++ src/hooks/useQuiz.ts | 21 +++++++++++ 4 files changed, 89 insertions(+) create mode 100644 spec/hooks/usePrevious/usePrevious.server.test.tsx create mode 100644 spec/hooks/usePrevious/usePrevious.test.tsx create mode 100644 src/hooks/usePrevious.ts diff --git a/spec/hooks/usePrevious/usePrevious.server.test.tsx b/spec/hooks/usePrevious/usePrevious.server.test.tsx new file mode 100644 index 00000000..e44aea09 --- /dev/null +++ b/spec/hooks/usePrevious/usePrevious.server.test.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { renderToString } from 'react-dom/server'; +import usePrevious from '../../../src/hooks/usePrevious'; + +describe(`${usePrevious.name} server`, () => { + function Component({ x }: { x: number }) { + const prevX = usePrevious(x); + return ( + <> + x={x};prevX={prevX} + + ); + } + + it('starts by having the previous value undefined', () => { + const view = renderToString(); + expect(view).toContain('x=10;prevX='); + }); +}); diff --git a/spec/hooks/usePrevious/usePrevious.test.tsx b/spec/hooks/usePrevious/usePrevious.test.tsx new file mode 100644 index 00000000..9c2cc594 --- /dev/null +++ b/spec/hooks/usePrevious/usePrevious.test.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import usePrevious from '../../../src/hooks/usePrevious'; + +describe(`${usePrevious.name}`, () => { + function Component({ x }: { x: number }) { + const prevX = usePrevious(x); + return ( + <> + x={x};prevX={prevX} + + ); + } + + it('starts by having the previous value undefined', () => { + const { container } = render(); + expect(container).toHaveTextContent('x=10'); + expect(container).toHaveTextContent('prevX='); + }); + + it('changes the previous value when rendered again with a different value', () => { + const { container, rerender } = render(); + rerender(); + expect(container).toHaveTextContent('x=11'); + expect(container).toHaveTextContent('prevX=10'); + }); + + it('does not change the previous value if rendered again with the same value', () => { + const { container, rerender } = render(); + rerender(); + rerender(); + expect(container).toHaveTextContent('x=11'); + expect(container).toHaveTextContent('prevX=10'); + }); +}); diff --git a/src/hooks/usePrevious.ts b/src/hooks/usePrevious.ts new file mode 100644 index 00000000..97e75a95 --- /dev/null +++ b/src/hooks/usePrevious.ts @@ -0,0 +1,14 @@ +import { useRef } from 'react'; + +export default function usePrevious(value: Type): Type | undefined { + const latest = useRef(value); + const previous = useRef(); + + if (latest.current !== value) { + previous.current = latest.current; + } + + latest.current = value; + + return previous.current; +} diff --git a/src/hooks/useQuiz.ts b/src/hooks/useQuiz.ts index 86f27cd0..35ae2fe4 100644 --- a/src/hooks/useQuiz.ts +++ b/src/hooks/useQuiz.ts @@ -6,6 +6,9 @@ import usePropsGetters from './usePropsGetters'; import usePrimaryColorStyles from './usePrimaryColorStyles'; import useQuizEvents from './useQuizEvents'; import useQuizState from './useQuizState'; +import usePrevious from './usePrevious'; +import { QuestionTypes, QuizAPIActionTypes } from '../components/CioQuiz/actions'; +import { resetQuizSessionStorageState } from '../utils'; const useQuiz: UseQuiz = (quizOptions) => { const { apiKey, cioJsClient, primaryColor, resultsPageOptions } = quizOptions; @@ -39,6 +42,24 @@ const useQuiz: UseQuiz = (quizOptions) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const { quizId } = quizOptions; + const { dispatchApiState, dispatchLocalState } = quizState; + + const prevQuizId = usePrevious(quizId); + + useEffect(() => { + if (quizId === prevQuizId) return; + if (!prevQuizId) return; + dispatchLocalState({ + type: QuestionTypes.Reset, + }); + dispatchApiState({ + type: QuizAPIActionTypes.RESET_QUIZ, + }); + resetQuizSessionStorageState(quizSessionStorageState.key); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [quizId, prevQuizId]); + return { cioClient, state: {