Skip to content

Commit

Permalink
finish exercise 1
Browse files Browse the repository at this point in the history
  • Loading branch information
kentcdodds committed Mar 4, 2024
1 parent fbaa2b1 commit 8e2b802
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 0 deletions.
8 changes: 8 additions & 0 deletions exercises/01.managing-ui-state/02.solution.control/README.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
# Controlling Inputs

πŸ‘¨β€πŸ’Ό Great! Now you can add/remove each of these tags to the search when they're
checked. Programmatically controlling the input value is why you use the `value`
prop.

But the feature is incomplete because a user could manually type the tag into
the search input and it would not be reflected in the checkbox. Let's look at
that next.
69 changes: 69 additions & 0 deletions exercises/01.managing-ui-state/03.problem.derive/README.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,70 @@
# Derive State

πŸ¦‰ Often, it can be easy to think you need to keep track of two elements of
state when you really only need one. For example, let's say you have a counter
that will display the number of times a user has clicked a button and also it
will display whether that number is odd or even. You might be tempted to write
the following code:

```tsx
import { useState } from 'react'

export default function Counter() {
const [count, setCount] = useState(0)
const [isEven, setIsEven] = useState(true)

function handleClick() {
const newCount = count + 1
setCount(newCount)
setIsEven(newCount % 2 === 0)
}

return (
<div>
<p>{count}</p>
<p>{isEven ? 'Even' : 'Odd'}</p>
<button onClick={handleClick}>Increment</button>
</div>
)
}
```

This code works, but it's not ideal because it's keeping track of two pieces of
state when it only needs to keep track of one. Imagine if we had multiple places
where the count could be changed. We'd have to remember to update the `isEven`
state in all of those places. This is a recipe for bugs.

Instead, we can derive the `isEven` state from the `count` state:

```tsx
import { useState } from 'react'

export default function Counter() {
const [count, setCount] = useState(0)

function handleClick() {
const newCount = count + 1
setCount(newCount)
}

// this is the derived state
const isEven = count % 2 === 0

return (
<div>
<p>{count}</p>
<p>{isEven ? 'Even' : 'Odd'}</p>
<button onClick={handleClick}>Increment</button>
</div>
)
}
```

This is a much better solution because we only have to keep track of the `count`
state. The `isEven` state is derived from the `count` state. This means we don't
have to worry about keeping the `isEven` state in sync with the `count` state.

πŸ‘¨β€πŸ’Ό Thanks Olivia! So what we want to do in this step is derive the checkboxes'
`checked` state based on whether the query contains the word they represent.

Give that a shot.
4 changes: 4 additions & 0 deletions exercises/01.managing-ui-state/03.solution.derive/README.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# Derive State

πŸ‘¨β€πŸ’Ό Awesome work! It looks really cool to have the checkboxes check and uncheck
automatically as you type! We're now controlling both all the inputs on here
all based on a single element of state. Well done.
19 changes: 19 additions & 0 deletions exercises/01.managing-ui-state/04.problem.init/README.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
# Initialize State

πŸ‘¨β€πŸ’Ό We want users to be able to share a link to this page with a prefilled
search. For example:
[`https://www.example.com/search?query=cat+dog`](/app/playground?query=cat+dog).

Right now, this won't work, because we don't have a way to initialize the
state of the search box from the URL. Let's fix that.

The `useState` hook supports an initial value. Right now we're just passing
`''` as the initial value, but we can use the `URLSearchParams` API to get the
query string from the URL and use that as the initial value.

```tsx
const params = new URLSearchParams(window.location.search)
const initialQuery = params.get('query') ?? ''
```

Then you can pass that `initialQuery` to `useState`. Give that a shot and then
the link above should work!

0 comments on commit 8e2b802

Please sign in to comment.