From 7b7eb57d9a4edcaf57ea78044bd0ccd67eae3b83 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 21 Mar 2024 12:06:20 -0600 Subject: [PATCH] add state initializers back --- .../01.problem.initial/README.mdx | 11 ++++ .../01.problem.initial/app.tsx | 16 ++++++ .../01.problem.initial}/index.css | 0 .../01.problem.initial}/index.tsx | 0 .../01.problem.initial/toggle.tsx | 55 ++++++++++++++++++ .../01.solution.initial/README.mdx | 4 ++ .../01.solution.initial/app.tsx | 13 +++++ .../01.solution.initial}/index.css | 0 .../01.solution.initial}/index.tsx | 0 .../01.solution.initial/toggle.tsx | 52 +++++++++++++++++ .../02.problem.stability/README.mdx | 16 ++++++ .../02.problem.stability/app.tsx | 18 ++++++ .../02.problem.stability}/index.css | 0 .../02.problem.stability}/index.tsx | 0 .../02.problem.stability/toggle.tsx | 55 ++++++++++++++++++ .../02.solution.stability/README.mdx | 3 + .../02.solution.stability/app.tsx | 18 ++++++ .../02.solution.stability}/index.css | 0 .../02.solution.stability}/index.tsx | 0 .../02.solution.stability/toggle.tsx | 52 +++++++++++++++++ exercises/06.state-initializers/FINISHED.mdx | 9 +++ exercises/06.state-initializers/README.mdx | 57 +++++++++++++++++++ .../01.problem/README.mdx | 0 .../01.problem/app.tsx | 0 .../01.problem/index.css | 0 .../01.problem/index.tsx | 0 .../01.problem/toggle.tsx | 0 .../01.solution/README.mdx | 0 .../01.solution/app.tsx | 0 .../01.solution/click-limit.test.tsx | 0 .../01.solution/index.css | 0 .../01.solution/index.tsx | 0 .../01.solution/toggle.test.tsx | 0 .../01.solution/toggle.tsx | 0 .../02.problem.default/README.mdx | 0 .../02.problem.default/app.tsx | 0 .../02.problem.default/index.css | 1 + .../02.problem.default/index.tsx | 6 ++ .../02.problem.default/toggle.tsx | 0 .../02.solution.default/README.mdx | 0 .../02.solution.default/app.tsx | 0 .../02.solution.default/click-limit.test.tsx | 0 .../exporting-toggle-reducer.test.tsx | 0 .../02.solution.default/index.css | 1 + .../02.solution.default/index.tsx | 6 ++ .../02.solution.default/toggle.test.tsx | 0 .../02.solution.default/toggle.tsx | 0 .../FINISHED.mdx | 0 .../README.mdx | 0 .../01.problem/README.mdx | 0 .../01.problem/app.tsx | 0 .../08.control-props/01.problem/index.css | 1 + .../08.control-props/01.problem/index.tsx | 6 ++ .../01.problem/toggle.tsx | 0 .../01.solution/README.mdx | 0 .../01.solution/app.tsx | 0 .../08.control-props/01.solution/index.css | 1 + .../08.control-props/01.solution/index.tsx | 6 ++ .../01.solution/synchronized.test.tsx | 0 .../01.solution/toggle.tsx | 0 .../01.solution/uncontrolled.test.tsx | 0 .../FINISHED.mdx | 0 .../README.mdx | 0 63 files changed, 407 insertions(+) create mode 100644 exercises/06.state-initializers/01.problem.initial/README.mdx create mode 100644 exercises/06.state-initializers/01.problem.initial/app.tsx rename exercises/{06.state-reducer/01.problem => 06.state-initializers/01.problem.initial}/index.css (100%) rename exercises/{06.state-reducer/01.problem => 06.state-initializers/01.problem.initial}/index.tsx (100%) create mode 100644 exercises/06.state-initializers/01.problem.initial/toggle.tsx create mode 100644 exercises/06.state-initializers/01.solution.initial/README.mdx create mode 100644 exercises/06.state-initializers/01.solution.initial/app.tsx rename exercises/{06.state-reducer/01.solution => 06.state-initializers/01.solution.initial}/index.css (100%) rename exercises/{06.state-reducer/01.solution => 06.state-initializers/01.solution.initial}/index.tsx (100%) create mode 100644 exercises/06.state-initializers/01.solution.initial/toggle.tsx create mode 100644 exercises/06.state-initializers/02.problem.stability/README.mdx create mode 100644 exercises/06.state-initializers/02.problem.stability/app.tsx rename exercises/{06.state-reducer/02.problem.default => 06.state-initializers/02.problem.stability}/index.css (100%) rename exercises/{06.state-reducer/02.problem.default => 06.state-initializers/02.problem.stability}/index.tsx (100%) create mode 100644 exercises/06.state-initializers/02.problem.stability/toggle.tsx create mode 100644 exercises/06.state-initializers/02.solution.stability/README.mdx create mode 100644 exercises/06.state-initializers/02.solution.stability/app.tsx rename exercises/{06.state-reducer/02.solution.default => 06.state-initializers/02.solution.stability}/index.css (100%) rename exercises/{06.state-reducer/02.solution.default => 06.state-initializers/02.solution.stability}/index.tsx (100%) create mode 100644 exercises/06.state-initializers/02.solution.stability/toggle.tsx create mode 100644 exercises/06.state-initializers/FINISHED.mdx create mode 100644 exercises/06.state-initializers/README.mdx rename exercises/{06.state-reducer => 07.state-reducer}/01.problem/README.mdx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/01.problem/app.tsx (100%) rename exercises/{07.control-props => 07.state-reducer}/01.problem/index.css (100%) rename exercises/{07.control-props => 07.state-reducer}/01.problem/index.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/01.problem/toggle.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/01.solution/README.mdx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/01.solution/app.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/01.solution/click-limit.test.tsx (100%) rename exercises/{07.control-props => 07.state-reducer}/01.solution/index.css (100%) rename exercises/{07.control-props => 07.state-reducer}/01.solution/index.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/01.solution/toggle.test.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/01.solution/toggle.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/02.problem.default/README.mdx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/02.problem.default/app.tsx (100%) create mode 100644 exercises/07.state-reducer/02.problem.default/index.css create mode 100644 exercises/07.state-reducer/02.problem.default/index.tsx rename exercises/{06.state-reducer => 07.state-reducer}/02.problem.default/toggle.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/02.solution.default/README.mdx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/02.solution.default/app.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/02.solution.default/click-limit.test.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/02.solution.default/exporting-toggle-reducer.test.tsx (100%) create mode 100644 exercises/07.state-reducer/02.solution.default/index.css create mode 100644 exercises/07.state-reducer/02.solution.default/index.tsx rename exercises/{06.state-reducer => 07.state-reducer}/02.solution.default/toggle.test.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/02.solution.default/toggle.tsx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/FINISHED.mdx (100%) rename exercises/{06.state-reducer => 07.state-reducer}/README.mdx (100%) rename exercises/{07.control-props => 08.control-props}/01.problem/README.mdx (100%) rename exercises/{07.control-props => 08.control-props}/01.problem/app.tsx (100%) create mode 100644 exercises/08.control-props/01.problem/index.css create mode 100644 exercises/08.control-props/01.problem/index.tsx rename exercises/{07.control-props => 08.control-props}/01.problem/toggle.tsx (100%) rename exercises/{07.control-props => 08.control-props}/01.solution/README.mdx (100%) rename exercises/{07.control-props => 08.control-props}/01.solution/app.tsx (100%) create mode 100644 exercises/08.control-props/01.solution/index.css create mode 100644 exercises/08.control-props/01.solution/index.tsx rename exercises/{07.control-props => 08.control-props}/01.solution/synchronized.test.tsx (100%) rename exercises/{07.control-props => 08.control-props}/01.solution/toggle.tsx (100%) rename exercises/{07.control-props => 08.control-props}/01.solution/uncontrolled.test.tsx (100%) rename exercises/{07.control-props => 08.control-props}/FINISHED.mdx (100%) rename exercises/{07.control-props => 08.control-props}/README.mdx (100%) diff --git a/exercises/06.state-initializers/01.problem.initial/README.mdx b/exercises/06.state-initializers/01.problem.initial/README.mdx new file mode 100644 index 00000000..45ff4b33 --- /dev/null +++ b/exercises/06.state-initializers/01.problem.initial/README.mdx @@ -0,0 +1,11 @@ +# Initialize Toggle + +👨‍💼 Our toggle component should be able to be customizable for the initial state +and reset to the initial state. + +🧝‍♂️ I've updated the toggle component to use a reducer instead of `useState`. If +you'd like to back up, and do that yourself in the playground, by my guest. Or +you can check my work instead. + +👨‍💼 Please add a case in our reducer for the `reset` logic, and add an option to +our `useToggle` hook for setting the initialOn state. diff --git a/exercises/06.state-initializers/01.problem.initial/app.tsx b/exercises/06.state-initializers/01.problem.initial/app.tsx new file mode 100644 index 00000000..0c516a78 --- /dev/null +++ b/exercises/06.state-initializers/01.problem.initial/app.tsx @@ -0,0 +1,16 @@ +import { Switch } from '#shared/switch.tsx' +import { useToggle } from './toggle.tsx' + +export function App() { + // 🐨 add an initialOn option (set it to true) and get the reset callback from useToggle + const { on, getTogglerProps } = useToggle() + // 💣 delete this reset callback in favor of what you get from useToggle + const reset = () => {} + return ( +
+ +
+ +
+ ) +} diff --git a/exercises/06.state-reducer/01.problem/index.css b/exercises/06.state-initializers/01.problem.initial/index.css similarity index 100% rename from exercises/06.state-reducer/01.problem/index.css rename to exercises/06.state-initializers/01.problem.initial/index.css diff --git a/exercises/06.state-reducer/01.problem/index.tsx b/exercises/06.state-initializers/01.problem.initial/index.tsx similarity index 100% rename from exercises/06.state-reducer/01.problem/index.tsx rename to exercises/06.state-initializers/01.problem.initial/index.tsx diff --git a/exercises/06.state-initializers/01.problem.initial/toggle.tsx b/exercises/06.state-initializers/01.problem.initial/toggle.tsx new file mode 100644 index 00000000..328144be --- /dev/null +++ b/exercises/06.state-initializers/01.problem.initial/toggle.tsx @@ -0,0 +1,55 @@ +import { useReducer } from 'react' + +function callAll>( + ...fns: Array<((...args: Args) => unknown) | undefined> +) { + return (...args: Args) => fns.forEach(fn => fn?.(...args)) +} + +type ToggleState = { on: boolean } +type ToggleAction = { type: 'toggle' } +// 🦺 add an action type for reset: +// 💰 | { type: 'reset'; initialState: ToggleState } + +function toggleReducer(state: ToggleState, action: ToggleAction) { + switch (action.type) { + case 'toggle': { + return { on: !state.on } + } + // 🐨 add a case for 'reset' that simply returns the "initialState" + // which you can get from the action. + } +} + +// 🐨 We'll need to add an option for `initialOn` here (default to false) +export function useToggle() { + // 🐨 update the initialState object to use the initialOn option + const initialState = { on: false } + const [state, dispatch] = useReducer(toggleReducer, initialState) + const { on } = state + + const toggle = () => dispatch({ type: 'toggle' }) + + // 🐨 add a reset function here which dispatches a 'reset' type with your + // initialState object and calls `onReset` with the initialState.on value + + function getTogglerProps({ + onClick, + ...props + }: { + onClick?: React.ComponentProps<'button'>['onClick'] + } & Props) { + return { + 'aria-checked': on, + onClick: callAll(onClick, toggle), + ...props, + } + } + + return { + on, + toggle, + // 🐨 add your reset function here. + getTogglerProps, + } +} diff --git a/exercises/06.state-initializers/01.solution.initial/README.mdx b/exercises/06.state-initializers/01.solution.initial/README.mdx new file mode 100644 index 00000000..d61c6b47 --- /dev/null +++ b/exercises/06.state-initializers/01.solution.initial/README.mdx @@ -0,0 +1,4 @@ +# Initialize Toggle + +👨‍💼 Great job! Now we can initilize and reset the toggle component! But we've +discovered a bug. Let's look at that next. diff --git a/exercises/06.state-initializers/01.solution.initial/app.tsx b/exercises/06.state-initializers/01.solution.initial/app.tsx new file mode 100644 index 00000000..e4622bc0 --- /dev/null +++ b/exercises/06.state-initializers/01.solution.initial/app.tsx @@ -0,0 +1,13 @@ +import { Switch } from '#shared/switch.tsx' +import { useToggle } from './toggle.tsx' + +export function App() { + const { on, getTogglerProps, reset } = useToggle({ initialOn: true }) + return ( +
+ +
+ +
+ ) +} diff --git a/exercises/06.state-reducer/01.solution/index.css b/exercises/06.state-initializers/01.solution.initial/index.css similarity index 100% rename from exercises/06.state-reducer/01.solution/index.css rename to exercises/06.state-initializers/01.solution.initial/index.css diff --git a/exercises/06.state-reducer/01.solution/index.tsx b/exercises/06.state-initializers/01.solution.initial/index.tsx similarity index 100% rename from exercises/06.state-reducer/01.solution/index.tsx rename to exercises/06.state-initializers/01.solution.initial/index.tsx diff --git a/exercises/06.state-initializers/01.solution.initial/toggle.tsx b/exercises/06.state-initializers/01.solution.initial/toggle.tsx new file mode 100644 index 00000000..243f87ac --- /dev/null +++ b/exercises/06.state-initializers/01.solution.initial/toggle.tsx @@ -0,0 +1,52 @@ +import { useReducer } from 'react' + +function callAll>( + ...fns: Array<((...args: Args) => unknown) | undefined> +) { + return (...args: Args) => fns.forEach(fn => fn?.(...args)) +} + +type ToggleState = { on: boolean } +type ToggleAction = + | { type: 'toggle' } + | { type: 'reset'; initialState: ToggleState } + +function toggleReducer(state: ToggleState, action: ToggleAction) { + switch (action.type) { + case 'toggle': { + return { on: !state.on } + } + case 'reset': { + return action.initialState + } + } +} + +export function useToggle({ initialOn = false } = {}) { + const initialState = { on: initialOn } + const [state, dispatch] = useReducer(toggleReducer, initialState) + const { on } = state + + const toggle = () => dispatch({ type: 'toggle' }) + const reset = () => dispatch({ type: 'reset', initialState }) + + function getTogglerProps({ + onClick, + ...props + }: { + onClick?: React.ComponentProps<'button'>['onClick'] + } & Props) { + return { + 'aria-checked': on, + onClick: callAll(onClick, toggle), + ...props, + } + } + + return { + on, + toggle, + reset, + getTogglerProps, + } +} diff --git a/exercises/06.state-initializers/02.problem.stability/README.mdx b/exercises/06.state-initializers/02.problem.stability/README.mdx new file mode 100644 index 00000000..6c3059b3 --- /dev/null +++ b/exercises/06.state-initializers/02.problem.stability/README.mdx @@ -0,0 +1,16 @@ +# Stability + +👨‍💼 We've noticed that if someone passes an `initialOn` that's based on state, +then calling `reset` will sometimes change the state to the wrong value based on +what the `initialOn` was set to at the time the component was initialized. + +This is confusing and we want to make certain to avoid it. + +🧝‍♂️ I've put together a simple example of this for you to experiment with. You'll +notice we now have a button for toggling the `initialOn` state which we pass as +an option to `useToggle`. So if you toggle the `initialOn` state and then click +the reset button, you'll notice it resets to the current `initialOn` state, not +the original one. + +👨‍💼 This is a little confusing for users of the `useToggle` hook, so please fix +this issue! Thanks! diff --git a/exercises/06.state-initializers/02.problem.stability/app.tsx b/exercises/06.state-initializers/02.problem.stability/app.tsx new file mode 100644 index 00000000..b8b357fb --- /dev/null +++ b/exercises/06.state-initializers/02.problem.stability/app.tsx @@ -0,0 +1,18 @@ +import { useState } from 'react' +import { Switch } from '#shared/switch.tsx' +import { useToggle } from './toggle.tsx' + +export function App() { + const [initialOn, setInitialOn] = useState(true) + const { on, getTogglerProps, reset } = useToggle({ initialOn }) + return ( +
+ + +
+ +
+ ) +} diff --git a/exercises/06.state-reducer/02.problem.default/index.css b/exercises/06.state-initializers/02.problem.stability/index.css similarity index 100% rename from exercises/06.state-reducer/02.problem.default/index.css rename to exercises/06.state-initializers/02.problem.stability/index.css diff --git a/exercises/06.state-reducer/02.problem.default/index.tsx b/exercises/06.state-initializers/02.problem.stability/index.tsx similarity index 100% rename from exercises/06.state-reducer/02.problem.default/index.tsx rename to exercises/06.state-initializers/02.problem.stability/index.tsx diff --git a/exercises/06.state-initializers/02.problem.stability/toggle.tsx b/exercises/06.state-initializers/02.problem.stability/toggle.tsx new file mode 100644 index 00000000..c49df8bf --- /dev/null +++ b/exercises/06.state-initializers/02.problem.stability/toggle.tsx @@ -0,0 +1,55 @@ +import { useReducer } from 'react' + +function callAll>( + ...fns: Array<((...args: Args) => unknown) | undefined> +) { + return (...args: Args) => fns.forEach(fn => fn?.(...args)) +} + +type ToggleState = { on: boolean } +type ToggleAction = + | { type: 'toggle' } + | { type: 'reset'; initialState: ToggleState } + +function toggleReducer(state: ToggleState, action: ToggleAction) { + switch (action.type) { + case 'toggle': { + return { on: !state.on } + } + case 'reset': { + return action.initialState + } + } +} + +export function useToggle({ initialOn = false } = {}) { + // 🐨 wrap this in a useRef + const initialState = { on: initialOn } + // 🐨 pass the ref-ed initial state into useReducer + const [state, dispatch] = useReducer(toggleReducer, initialState) + const { on } = state + + const toggle = () => dispatch({ type: 'toggle' }) + // 🐨 make sure the ref-ed initial state gets passed here + const reset = () => dispatch({ type: 'reset', initialState }) + + function getTogglerProps({ + onClick, + ...props + }: { + onClick?: React.ComponentProps<'button'>['onClick'] + } & Props) { + return { + 'aria-checked': on, + onClick: callAll(onClick, toggle), + ...props, + } + } + + return { + on, + toggle, + reset, + getTogglerProps, + } +} diff --git a/exercises/06.state-initializers/02.solution.stability/README.mdx b/exercises/06.state-initializers/02.solution.stability/README.mdx new file mode 100644 index 00000000..c4292612 --- /dev/null +++ b/exercises/06.state-initializers/02.solution.stability/README.mdx @@ -0,0 +1,3 @@ +# Stability + +👨‍💼 Great. Now we've got some stability with our state initializer. Well done! diff --git a/exercises/06.state-initializers/02.solution.stability/app.tsx b/exercises/06.state-initializers/02.solution.stability/app.tsx new file mode 100644 index 00000000..b8b357fb --- /dev/null +++ b/exercises/06.state-initializers/02.solution.stability/app.tsx @@ -0,0 +1,18 @@ +import { useState } from 'react' +import { Switch } from '#shared/switch.tsx' +import { useToggle } from './toggle.tsx' + +export function App() { + const [initialOn, setInitialOn] = useState(true) + const { on, getTogglerProps, reset } = useToggle({ initialOn }) + return ( +
+ + +
+ +
+ ) +} diff --git a/exercises/06.state-reducer/02.solution.default/index.css b/exercises/06.state-initializers/02.solution.stability/index.css similarity index 100% rename from exercises/06.state-reducer/02.solution.default/index.css rename to exercises/06.state-initializers/02.solution.stability/index.css diff --git a/exercises/06.state-reducer/02.solution.default/index.tsx b/exercises/06.state-initializers/02.solution.stability/index.tsx similarity index 100% rename from exercises/06.state-reducer/02.solution.default/index.tsx rename to exercises/06.state-initializers/02.solution.stability/index.tsx diff --git a/exercises/06.state-initializers/02.solution.stability/toggle.tsx b/exercises/06.state-initializers/02.solution.stability/toggle.tsx new file mode 100644 index 00000000..b4754419 --- /dev/null +++ b/exercises/06.state-initializers/02.solution.stability/toggle.tsx @@ -0,0 +1,52 @@ +import { useReducer, useRef } from 'react' + +function callAll>( + ...fns: Array<((...args: Args) => unknown) | undefined> +) { + return (...args: Args) => fns.forEach(fn => fn?.(...args)) +} + +type ToggleState = { on: boolean } +type ToggleAction = + | { type: 'toggle' } + | { type: 'reset'; initialState: ToggleState } + +function toggleReducer(state: ToggleState, action: ToggleAction) { + switch (action.type) { + case 'toggle': { + return { on: !state.on } + } + case 'reset': { + return action.initialState + } + } +} + +export function useToggle({ initialOn = false } = {}) { + const initialState = useRef({ on: initialOn }).current + const [state, dispatch] = useReducer(toggleReducer, initialState) + const { on } = state + + const toggle = () => dispatch({ type: 'toggle' }) + const reset = () => dispatch({ type: 'reset', initialState }) + + function getTogglerProps({ + onClick, + ...props + }: { + onClick?: React.ComponentProps<'button'>['onClick'] + } & Props) { + return { + 'aria-checked': on, + onClick: callAll(onClick, toggle), + ...props, + } + } + + return { + on, + toggle, + reset, + getTogglerProps, + } +} diff --git a/exercises/06.state-initializers/FINISHED.mdx b/exercises/06.state-initializers/FINISHED.mdx new file mode 100644 index 00000000..91ee604f --- /dev/null +++ b/exercises/06.state-initializers/FINISHED.mdx @@ -0,0 +1,9 @@ +# State Initializer + +👨‍💼 Great job! You now know what to do to properly handle the initialization (and +reset) of your state. + +🦉 Keep in mind that the `key` prop can also be used as a way to reset the state +of a component, and it works pretty well. However it does require that +everything is unmounted and remounted, which may not be what you want depending +on the situation. diff --git a/exercises/06.state-initializers/README.mdx b/exercises/06.state-initializers/README.mdx new file mode 100644 index 00000000..57d986bc --- /dev/null +++ b/exercises/06.state-initializers/README.mdx @@ -0,0 +1,57 @@ +# State Initializer + + + **One liner:** The state initializer pattern is a way to initialize (and + reset) the state of a component in a predictable way. + + +This one is simple in concept: + +```tsx +function useCounter() { + const [count, setCount] = useState(0) + const increment = () => setCount(c => c + 1) + return { count, increment } +} +``` + +If I wanted to initialize the state of the count to a different value, I could +do so by passing an argument to the `useCounter` function: + +```tsx +function useCounter({ initialCount = 0 } = {}) { + const [count, setCount] = useState(initialCount) + const increment = () => setCount(c => c + 1) + return { count, increment } +} +``` + +And often when you have a state initializer, you also have a state resetter: + +```tsx +function useCounter({ initialCount = 0 } = {}) { + const [count, setCount] = useState(initialCount) + const increment = () => setCount(c => c + 1) + const reset = () => setCount(initialCount) + return { count, increment, reset } +} +``` + +But there's a catch. If you truly want to reset the component to its _initial_ +state, then you need to make certain that any changes to the `initialCount` are +ignored! + +You can do this, by using a `ref` which will keep the initial value constant +across renders: + +```tsx +function useCounter({ initialCount = 0 } = {}) { + const initialCountRef = useRef(initialCount) + const [count, setCount] = useState(initialCountRef.current) + const increment = () => setCount(c => c + 1) + const reset = () => setCount(initialCountRef.current) + return { count, increment, reset } +} +``` + +And that's the crux of the state initializer pattern. diff --git a/exercises/06.state-reducer/01.problem/README.mdx b/exercises/07.state-reducer/01.problem/README.mdx similarity index 100% rename from exercises/06.state-reducer/01.problem/README.mdx rename to exercises/07.state-reducer/01.problem/README.mdx diff --git a/exercises/06.state-reducer/01.problem/app.tsx b/exercises/07.state-reducer/01.problem/app.tsx similarity index 100% rename from exercises/06.state-reducer/01.problem/app.tsx rename to exercises/07.state-reducer/01.problem/app.tsx diff --git a/exercises/07.control-props/01.problem/index.css b/exercises/07.state-reducer/01.problem/index.css similarity index 100% rename from exercises/07.control-props/01.problem/index.css rename to exercises/07.state-reducer/01.problem/index.css diff --git a/exercises/07.control-props/01.problem/index.tsx b/exercises/07.state-reducer/01.problem/index.tsx similarity index 100% rename from exercises/07.control-props/01.problem/index.tsx rename to exercises/07.state-reducer/01.problem/index.tsx diff --git a/exercises/06.state-reducer/01.problem/toggle.tsx b/exercises/07.state-reducer/01.problem/toggle.tsx similarity index 100% rename from exercises/06.state-reducer/01.problem/toggle.tsx rename to exercises/07.state-reducer/01.problem/toggle.tsx diff --git a/exercises/06.state-reducer/01.solution/README.mdx b/exercises/07.state-reducer/01.solution/README.mdx similarity index 100% rename from exercises/06.state-reducer/01.solution/README.mdx rename to exercises/07.state-reducer/01.solution/README.mdx diff --git a/exercises/06.state-reducer/01.solution/app.tsx b/exercises/07.state-reducer/01.solution/app.tsx similarity index 100% rename from exercises/06.state-reducer/01.solution/app.tsx rename to exercises/07.state-reducer/01.solution/app.tsx diff --git a/exercises/06.state-reducer/01.solution/click-limit.test.tsx b/exercises/07.state-reducer/01.solution/click-limit.test.tsx similarity index 100% rename from exercises/06.state-reducer/01.solution/click-limit.test.tsx rename to exercises/07.state-reducer/01.solution/click-limit.test.tsx diff --git a/exercises/07.control-props/01.solution/index.css b/exercises/07.state-reducer/01.solution/index.css similarity index 100% rename from exercises/07.control-props/01.solution/index.css rename to exercises/07.state-reducer/01.solution/index.css diff --git a/exercises/07.control-props/01.solution/index.tsx b/exercises/07.state-reducer/01.solution/index.tsx similarity index 100% rename from exercises/07.control-props/01.solution/index.tsx rename to exercises/07.state-reducer/01.solution/index.tsx diff --git a/exercises/06.state-reducer/01.solution/toggle.test.tsx b/exercises/07.state-reducer/01.solution/toggle.test.tsx similarity index 100% rename from exercises/06.state-reducer/01.solution/toggle.test.tsx rename to exercises/07.state-reducer/01.solution/toggle.test.tsx diff --git a/exercises/06.state-reducer/01.solution/toggle.tsx b/exercises/07.state-reducer/01.solution/toggle.tsx similarity index 100% rename from exercises/06.state-reducer/01.solution/toggle.tsx rename to exercises/07.state-reducer/01.solution/toggle.tsx diff --git a/exercises/06.state-reducer/02.problem.default/README.mdx b/exercises/07.state-reducer/02.problem.default/README.mdx similarity index 100% rename from exercises/06.state-reducer/02.problem.default/README.mdx rename to exercises/07.state-reducer/02.problem.default/README.mdx diff --git a/exercises/06.state-reducer/02.problem.default/app.tsx b/exercises/07.state-reducer/02.problem.default/app.tsx similarity index 100% rename from exercises/06.state-reducer/02.problem.default/app.tsx rename to exercises/07.state-reducer/02.problem.default/app.tsx diff --git a/exercises/07.state-reducer/02.problem.default/index.css b/exercises/07.state-reducer/02.problem.default/index.css new file mode 100644 index 00000000..fc21ae80 --- /dev/null +++ b/exercises/07.state-reducer/02.problem.default/index.css @@ -0,0 +1 @@ +@import '/switch.styles.css'; diff --git a/exercises/07.state-reducer/02.problem.default/index.tsx b/exercises/07.state-reducer/02.problem.default/index.tsx new file mode 100644 index 00000000..72b36c07 --- /dev/null +++ b/exercises/07.state-reducer/02.problem.default/index.tsx @@ -0,0 +1,6 @@ +import * as ReactDOM from 'react-dom/client' +import { App } from './app.tsx' + +const rootEl = document.createElement('div') +document.body.append(rootEl) +ReactDOM.createRoot(rootEl).render() diff --git a/exercises/06.state-reducer/02.problem.default/toggle.tsx b/exercises/07.state-reducer/02.problem.default/toggle.tsx similarity index 100% rename from exercises/06.state-reducer/02.problem.default/toggle.tsx rename to exercises/07.state-reducer/02.problem.default/toggle.tsx diff --git a/exercises/06.state-reducer/02.solution.default/README.mdx b/exercises/07.state-reducer/02.solution.default/README.mdx similarity index 100% rename from exercises/06.state-reducer/02.solution.default/README.mdx rename to exercises/07.state-reducer/02.solution.default/README.mdx diff --git a/exercises/06.state-reducer/02.solution.default/app.tsx b/exercises/07.state-reducer/02.solution.default/app.tsx similarity index 100% rename from exercises/06.state-reducer/02.solution.default/app.tsx rename to exercises/07.state-reducer/02.solution.default/app.tsx diff --git a/exercises/06.state-reducer/02.solution.default/click-limit.test.tsx b/exercises/07.state-reducer/02.solution.default/click-limit.test.tsx similarity index 100% rename from exercises/06.state-reducer/02.solution.default/click-limit.test.tsx rename to exercises/07.state-reducer/02.solution.default/click-limit.test.tsx diff --git a/exercises/06.state-reducer/02.solution.default/exporting-toggle-reducer.test.tsx b/exercises/07.state-reducer/02.solution.default/exporting-toggle-reducer.test.tsx similarity index 100% rename from exercises/06.state-reducer/02.solution.default/exporting-toggle-reducer.test.tsx rename to exercises/07.state-reducer/02.solution.default/exporting-toggle-reducer.test.tsx diff --git a/exercises/07.state-reducer/02.solution.default/index.css b/exercises/07.state-reducer/02.solution.default/index.css new file mode 100644 index 00000000..fc21ae80 --- /dev/null +++ b/exercises/07.state-reducer/02.solution.default/index.css @@ -0,0 +1 @@ +@import '/switch.styles.css'; diff --git a/exercises/07.state-reducer/02.solution.default/index.tsx b/exercises/07.state-reducer/02.solution.default/index.tsx new file mode 100644 index 00000000..72b36c07 --- /dev/null +++ b/exercises/07.state-reducer/02.solution.default/index.tsx @@ -0,0 +1,6 @@ +import * as ReactDOM from 'react-dom/client' +import { App } from './app.tsx' + +const rootEl = document.createElement('div') +document.body.append(rootEl) +ReactDOM.createRoot(rootEl).render() diff --git a/exercises/06.state-reducer/02.solution.default/toggle.test.tsx b/exercises/07.state-reducer/02.solution.default/toggle.test.tsx similarity index 100% rename from exercises/06.state-reducer/02.solution.default/toggle.test.tsx rename to exercises/07.state-reducer/02.solution.default/toggle.test.tsx diff --git a/exercises/06.state-reducer/02.solution.default/toggle.tsx b/exercises/07.state-reducer/02.solution.default/toggle.tsx similarity index 100% rename from exercises/06.state-reducer/02.solution.default/toggle.tsx rename to exercises/07.state-reducer/02.solution.default/toggle.tsx diff --git a/exercises/06.state-reducer/FINISHED.mdx b/exercises/07.state-reducer/FINISHED.mdx similarity index 100% rename from exercises/06.state-reducer/FINISHED.mdx rename to exercises/07.state-reducer/FINISHED.mdx diff --git a/exercises/06.state-reducer/README.mdx b/exercises/07.state-reducer/README.mdx similarity index 100% rename from exercises/06.state-reducer/README.mdx rename to exercises/07.state-reducer/README.mdx diff --git a/exercises/07.control-props/01.problem/README.mdx b/exercises/08.control-props/01.problem/README.mdx similarity index 100% rename from exercises/07.control-props/01.problem/README.mdx rename to exercises/08.control-props/01.problem/README.mdx diff --git a/exercises/07.control-props/01.problem/app.tsx b/exercises/08.control-props/01.problem/app.tsx similarity index 100% rename from exercises/07.control-props/01.problem/app.tsx rename to exercises/08.control-props/01.problem/app.tsx diff --git a/exercises/08.control-props/01.problem/index.css b/exercises/08.control-props/01.problem/index.css new file mode 100644 index 00000000..fc21ae80 --- /dev/null +++ b/exercises/08.control-props/01.problem/index.css @@ -0,0 +1 @@ +@import '/switch.styles.css'; diff --git a/exercises/08.control-props/01.problem/index.tsx b/exercises/08.control-props/01.problem/index.tsx new file mode 100644 index 00000000..72b36c07 --- /dev/null +++ b/exercises/08.control-props/01.problem/index.tsx @@ -0,0 +1,6 @@ +import * as ReactDOM from 'react-dom/client' +import { App } from './app.tsx' + +const rootEl = document.createElement('div') +document.body.append(rootEl) +ReactDOM.createRoot(rootEl).render() diff --git a/exercises/07.control-props/01.problem/toggle.tsx b/exercises/08.control-props/01.problem/toggle.tsx similarity index 100% rename from exercises/07.control-props/01.problem/toggle.tsx rename to exercises/08.control-props/01.problem/toggle.tsx diff --git a/exercises/07.control-props/01.solution/README.mdx b/exercises/08.control-props/01.solution/README.mdx similarity index 100% rename from exercises/07.control-props/01.solution/README.mdx rename to exercises/08.control-props/01.solution/README.mdx diff --git a/exercises/07.control-props/01.solution/app.tsx b/exercises/08.control-props/01.solution/app.tsx similarity index 100% rename from exercises/07.control-props/01.solution/app.tsx rename to exercises/08.control-props/01.solution/app.tsx diff --git a/exercises/08.control-props/01.solution/index.css b/exercises/08.control-props/01.solution/index.css new file mode 100644 index 00000000..fc21ae80 --- /dev/null +++ b/exercises/08.control-props/01.solution/index.css @@ -0,0 +1 @@ +@import '/switch.styles.css'; diff --git a/exercises/08.control-props/01.solution/index.tsx b/exercises/08.control-props/01.solution/index.tsx new file mode 100644 index 00000000..72b36c07 --- /dev/null +++ b/exercises/08.control-props/01.solution/index.tsx @@ -0,0 +1,6 @@ +import * as ReactDOM from 'react-dom/client' +import { App } from './app.tsx' + +const rootEl = document.createElement('div') +document.body.append(rootEl) +ReactDOM.createRoot(rootEl).render() diff --git a/exercises/07.control-props/01.solution/synchronized.test.tsx b/exercises/08.control-props/01.solution/synchronized.test.tsx similarity index 100% rename from exercises/07.control-props/01.solution/synchronized.test.tsx rename to exercises/08.control-props/01.solution/synchronized.test.tsx diff --git a/exercises/07.control-props/01.solution/toggle.tsx b/exercises/08.control-props/01.solution/toggle.tsx similarity index 100% rename from exercises/07.control-props/01.solution/toggle.tsx rename to exercises/08.control-props/01.solution/toggle.tsx diff --git a/exercises/07.control-props/01.solution/uncontrolled.test.tsx b/exercises/08.control-props/01.solution/uncontrolled.test.tsx similarity index 100% rename from exercises/07.control-props/01.solution/uncontrolled.test.tsx rename to exercises/08.control-props/01.solution/uncontrolled.test.tsx diff --git a/exercises/07.control-props/FINISHED.mdx b/exercises/08.control-props/FINISHED.mdx similarity index 100% rename from exercises/07.control-props/FINISHED.mdx rename to exercises/08.control-props/FINISHED.mdx diff --git a/exercises/07.control-props/README.mdx b/exercises/08.control-props/README.mdx similarity index 100% rename from exercises/07.control-props/README.mdx rename to exercises/08.control-props/README.mdx