diff --git a/exercises/02.sychronizing-side-effects/01.problem.effects/index.tsx b/exercises/02.sychronizing-side-effects/01.problem.effects/index.tsx index b66e7e736..a836e4cd8 100644 --- a/exercises/02.sychronizing-side-effects/01.problem.effects/index.tsx +++ b/exercises/02.sychronizing-side-effects/01.problem.effects/index.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' import * as ReactDOM from 'react-dom/client' import { generateGradient, getMatchingPosts } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function App() { // NOTE: this will not work with server rendering, but in a real app you can @@ -35,7 +35,7 @@ function App() {
{ e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/02.sychronizing-side-effects/01.solution.effects/index.tsx b/exercises/02.sychronizing-side-effects/01.solution.effects/index.tsx index 64a186744..77e4d7254 100644 --- a/exercises/02.sychronizing-side-effects/01.solution.effects/index.tsx +++ b/exercises/02.sychronizing-side-effects/01.solution.effects/index.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import * as ReactDOM from 'react-dom/client' import { generateGradient, getMatchingPosts } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function App() { // NOTE: this will not work with server rendering, but in a real app you can @@ -30,7 +30,7 @@ function App() { { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/02.sychronizing-side-effects/02.problem.deps/index.tsx b/exercises/02.sychronizing-side-effects/02.problem.deps/index.tsx index db98cc140..b27188ae7 100644 --- a/exercises/02.sychronizing-side-effects/02.problem.deps/index.tsx +++ b/exercises/02.sychronizing-side-effects/02.problem.deps/index.tsx @@ -6,7 +6,7 @@ eslint import { useEffect, useState } from 'react' import * as ReactDOM from 'react-dom/client' import { generateGradient, getMatchingPosts } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' // 🐨 create a getQueryParam function which: // 1. creates a new params object @@ -40,7 +40,7 @@ function App() { { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/02.sychronizing-side-effects/02.solution.deps/index.tsx b/exercises/02.sychronizing-side-effects/02.solution.deps/index.tsx index fa6380d3a..1eaba14ee 100644 --- a/exercises/02.sychronizing-side-effects/02.solution.deps/index.tsx +++ b/exercises/02.sychronizing-side-effects/02.solution.deps/index.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import * as ReactDOM from 'react-dom/client' import { generateGradient, getMatchingPosts } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function getQueryParam() { const params = new URLSearchParams(window.location.search) @@ -33,7 +33,7 @@ function App() { { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/02.sychronizing-side-effects/03.problem.cleanup/index.tsx b/exercises/02.sychronizing-side-effects/03.problem.cleanup/index.tsx index 4c03268a7..4edd0b759 100644 --- a/exercises/02.sychronizing-side-effects/03.problem.cleanup/index.tsx +++ b/exercises/02.sychronizing-side-effects/03.problem.cleanup/index.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import * as ReactDOM from 'react-dom/client' import { generateGradient, getMatchingPosts } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function getQueryParam() { const params = new URLSearchParams(window.location.search) @@ -37,7 +37,7 @@ function App() { { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/02.sychronizing-side-effects/03.solution.cleanup/index.tsx b/exercises/02.sychronizing-side-effects/03.solution.cleanup/index.tsx index 3b5a887ba..2b4e94720 100644 --- a/exercises/02.sychronizing-side-effects/03.solution.cleanup/index.tsx +++ b/exercises/02.sychronizing-side-effects/03.solution.cleanup/index.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import * as ReactDOM from 'react-dom/client' import { generateGradient, getMatchingPosts } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function getQueryParam() { const params = new URLSearchParams(window.location.search) @@ -38,7 +38,7 @@ function App() { { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/03.lifting-state/01.problem.lift/index.tsx b/exercises/03.lifting-state/01.problem.lift/index.tsx index 941f6267d..52cf0641c 100644 --- a/exercises/03.lifting-state/01.problem.lift/index.tsx +++ b/exercises/03.lifting-state/01.problem.lift/index.tsx @@ -5,7 +5,7 @@ import { generateGradient, getMatchingPosts, } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function getQueryParam() { const params = new URLSearchParams(window.location.search) @@ -35,13 +35,13 @@ function Form() { const catChecked = words.includes('cat') const caterpillarChecked = words.includes('caterpillar') + // 🐨 move this up to the App as well useEffect(() => { const updateQuery = () => setQuery(getQueryParam()) window.addEventListener('popstate', updateQuery) return () => { window.removeEventListener('popstate', updateQuery) } - // 🐨 add setQuery to the dependency array here }, []) function handleCheck(tag: string, checked: boolean) { @@ -53,7 +53,7 @@ function Form() { { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/03.lifting-state/01.solution.lift/index.tsx b/exercises/03.lifting-state/01.solution.lift/index.tsx index 5cd92f197..b2bb455c2 100644 --- a/exercises/03.lifting-state/01.solution.lift/index.tsx +++ b/exercises/03.lifting-state/01.solution.lift/index.tsx @@ -5,7 +5,7 @@ import { generateGradient, getMatchingPosts, } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function getQueryParam() { const params = new URLSearchParams(window.location.search) @@ -14,6 +14,15 @@ function getQueryParam() { function App() { const [query, setQuery] = useState(getQueryParam) + + useEffect(() => { + const updateQuery = () => setQuery(getQueryParam()) + window.addEventListener('popstate', updateQuery) + return () => { + window.removeEventListener('popstate', updateQuery) + } + }, [setQuery]) + return (
@@ -35,14 +44,6 @@ function Form({ const catChecked = words.includes('cat') const caterpillarChecked = words.includes('caterpillar') - useEffect(() => { - const updateQuery = () => setQuery(getQueryParam()) - window.addEventListener('popstate', updateQuery) - return () => { - window.removeEventListener('popstate', updateQuery) - } - }, [setQuery]) - function handleCheck(tag: string, checked: boolean) { const newWords = checked ? [...words, tag] : words.filter(w => w !== tag) setQuery(newWords.filter(Boolean).join(' ').trim()) @@ -52,7 +53,7 @@ function Form({ { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/03.lifting-state/02.problem.lift-array/index.tsx b/exercises/03.lifting-state/02.problem.lift-array/index.tsx index e357ddfc4..7a95b5306 100644 --- a/exercises/03.lifting-state/02.problem.lift-array/index.tsx +++ b/exercises/03.lifting-state/02.problem.lift-array/index.tsx @@ -5,7 +5,7 @@ import { generateGradient, getMatchingPosts, } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function getQueryParam() { const params = new URLSearchParams(window.location.search) @@ -14,6 +14,15 @@ function getQueryParam() { function App() { const [query, setQuery] = useState(getQueryParam) + + useEffect(() => { + const updateQuery = () => setQuery(getQueryParam()) + window.addEventListener('popstate', updateQuery) + return () => { + window.removeEventListener('popstate', updateQuery) + } + }, [setQuery]) + return (
@@ -35,14 +44,6 @@ function Form({ const catChecked = words.includes('cat') const caterpillarChecked = words.includes('caterpillar') - useEffect(() => { - const updateQuery = () => setQuery(getQueryParam()) - window.addEventListener('popstate', updateQuery) - return () => { - window.removeEventListener('popstate', updateQuery) - } - }, [setQuery]) - function handleCheck(tag: string, checked: boolean) { const newWords = checked ? [...words, tag] : words.filter(w => w !== tag) setQuery(newWords.filter(Boolean).join(' ').trim()) @@ -52,7 +53,7 @@ function Form({ { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/03.lifting-state/02.solution.lift-array/index.tsx b/exercises/03.lifting-state/02.solution.lift-array/index.tsx index 78209c170..71f4c0a48 100644 --- a/exercises/03.lifting-state/02.solution.lift-array/index.tsx +++ b/exercises/03.lifting-state/02.solution.lift-array/index.tsx @@ -5,7 +5,7 @@ import { generateGradient, getMatchingPosts, } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function getQueryParam() { const params = new URLSearchParams(window.location.search) @@ -14,6 +14,15 @@ function getQueryParam() { function App() { const [query, setQuery] = useState(getQueryParam) + + useEffect(() => { + const updateQuery = () => setQuery(getQueryParam()) + window.addEventListener('popstate', updateQuery) + return () => { + window.removeEventListener('popstate', updateQuery) + } + }, [setQuery]) + return (
@@ -35,14 +44,6 @@ function Form({ const catChecked = words.includes('cat') const caterpillarChecked = words.includes('caterpillar') - useEffect(() => { - const updateQuery = () => setQuery(getQueryParam()) - window.addEventListener('popstate', updateQuery) - return () => { - window.removeEventListener('popstate', updateQuery) - } - }, [setQuery]) - function handleCheck(tag: string, checked: boolean) { const newWords = checked ? [...words, tag] : words.filter(w => w !== tag) setQuery(newWords.filter(Boolean).join(' ').trim()) @@ -52,7 +53,7 @@ function Form({ { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/03.lifting-state/03.problem.colocate/index.tsx b/exercises/03.lifting-state/03.problem.colocate/index.tsx index b7566038e..6e1f7c772 100644 --- a/exercises/03.lifting-state/03.problem.colocate/index.tsx +++ b/exercises/03.lifting-state/03.problem.colocate/index.tsx @@ -5,7 +5,7 @@ import { generateGradient, getMatchingPosts, } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function getQueryParam() { const params = new URLSearchParams(window.location.search) @@ -14,6 +14,15 @@ function getQueryParam() { function App() { const [query, setQuery] = useState(getQueryParam) + + useEffect(() => { + const updateQuery = () => setQuery(getQueryParam()) + window.addEventListener('popstate', updateQuery) + return () => { + window.removeEventListener('popstate', updateQuery) + } + }, [setQuery]) + return (
@@ -35,14 +44,6 @@ function Form({ const catChecked = words.includes('cat') const caterpillarChecked = words.includes('caterpillar') - useEffect(() => { - const updateQuery = () => setQuery(getQueryParam()) - window.addEventListener('popstate', updateQuery) - return () => { - window.removeEventListener('popstate', updateQuery) - } - }, [setQuery]) - function handleCheck(tag: string, checked: boolean) { const newWords = checked ? [...words, tag] : words.filter(w => w !== tag) setQuery(newWords.filter(Boolean).join(' ').trim()) @@ -52,7 +53,7 @@ function Form({ { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/03.lifting-state/03.solution.colocate/index.tsx b/exercises/03.lifting-state/03.solution.colocate/index.tsx index d739304f2..67d7d24d6 100644 --- a/exercises/03.lifting-state/03.solution.colocate/index.tsx +++ b/exercises/03.lifting-state/03.solution.colocate/index.tsx @@ -5,7 +5,7 @@ import { generateGradient, getMatchingPosts, } from '#shared/blog-posts' -import { setSearchParams } from '#shared/utils' +import { setGlobalSearchParams } from '#shared/utils' function getQueryParam() { const params = new URLSearchParams(window.location.search) @@ -14,6 +14,15 @@ function getQueryParam() { function App() { const [query, setQuery] = useState(getQueryParam) + + useEffect(() => { + const updateQuery = () => setQuery(getQueryParam()) + window.addEventListener('popstate', updateQuery) + return () => { + window.removeEventListener('popstate', updateQuery) + } + }, [setQuery]) + return (
@@ -35,14 +44,6 @@ function Form({ const catChecked = words.includes('cat') const caterpillarChecked = words.includes('caterpillar') - useEffect(() => { - const updateQuery = () => setQuery(getQueryParam()) - window.addEventListener('popstate', updateQuery) - return () => { - window.removeEventListener('popstate', updateQuery) - } - }, [setQuery]) - function handleCheck(tag: string, checked: boolean) { const newWords = checked ? [...words, tag] : words.filter(w => w !== tag) setQuery(newWords.filter(Boolean).join(' ').trim()) @@ -52,7 +53,7 @@ function Form({ { e.preventDefault() - setSearchParams({ query }) + setGlobalSearchParams({ query }) }} >
diff --git a/exercises/06.tic-tac-toe/03.solution.history/index.tsx b/exercises/06.tic-tac-toe/03.solution.history/index.tsx index 5a43e8590..78c657161 100644 --- a/exercises/06.tic-tac-toe/03.solution.history/index.tsx +++ b/exercises/06.tic-tac-toe/03.solution.history/index.tsx @@ -48,7 +48,7 @@ function Board({ ) } -const defaultState = { +const defaultState: GameState = { history: [Array(9).fill(null)], currentStep: 0, } diff --git a/shared/tic-tac-toe-utils.tsx b/shared/tic-tac-toe-utils.tsx index 34efc6285..701f6cac4 100644 --- a/shared/tic-tac-toe-utils.tsx +++ b/shared/tic-tac-toe-utils.tsx @@ -21,7 +21,6 @@ function isSquaresArray(value: unknown): value is Squares { function isHistory(value: unknown): value is Array { if (!isArray(value)) return false - if (value.length !== 9) return false if (!value.every(isSquaresArray)) return false return true } diff --git a/shared/utils.tsx b/shared/utils.tsx index 00e36eeb9..de31b8814 100644 --- a/shared/utils.tsx +++ b/shared/utils.tsx @@ -6,7 +6,7 @@ * @param {boolean} options.replace - Whether to replace the current URL in the history or not. * @returns {URLSearchParams} - The updated search parameters. */ -export function setSearchParams( +export function setGlobalSearchParams( params: Record, options: { replace?: boolean } = {}, ) {