Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/__tests__/06.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import * as React from 'react'
import {alfredTip} from '@kentcdodds/react-workshop-app/test-utils'
import {render, screen} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import App from '../final/06'
// import App from '../exercise/06'
// import App from '../final/06'
import App from '../exercise/06'

beforeEach(() => jest.spyOn(window, 'fetch'))
afterEach(() => window.fetch.mockRestore())
Expand Down
84 changes: 60 additions & 24 deletions src/exercise/06.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,57 @@
// useEffect: HTTP requests
// http://localhost:3000/isolated/exercise/06.js

import * as React from 'react'
// 🐨 you'll want the following additional things from '../pokemon':
// fetchPokemon: the function we call to get the pokemon info
// PokemonInfoFallback: the thing we show while we're loading the pokemon info
// PokemonDataView: the stuff we use to display the pokemon info
import {PokemonForm} from '../pokemon'
import * as React from 'react';
import {ErrorBoundary} from 'react-error-boundary';
import {
PokemonForm,
fetchPokemon,
PokemonInfoFallback,
PokemonDataView,
} from '../pokemon';

function PokemonInfo({pokemonName}) {
// 🐨 Have state for the pokemon (null)
// 🐨 use React.useEffect where the callback should be called whenever the
// pokemon name changes.
// 💰 DON'T FORGET THE DEPENDENCIES ARRAY!
// 💰 if the pokemonName is falsy (an empty string) then don't bother making the request (exit early).
// 🐨 before calling `fetchPokemon`, clear the current pokemon state by setting it to null
// 💰 Use the `fetchPokemon` function to fetch a pokemon by its name:
// fetchPokemon('Pikachu').then(
// pokemonData => { /* update all the state here */},
// )
// 🐨 return the following things based on the `pokemon` state and `pokemonName` prop:
// 1. no pokemonName: 'Submit a pokemon'
// 2. pokemonName but no pokemon: <PokemonInfoFallback name={pokemonName} />
// 3. pokemon: <PokemonDataView pokemon={pokemon} />

// 💣 remove this
return 'TODO'
const [state, setState] = React.useState({
status: 'idle',
pokemon: null,
error: null,
});
const {status, pokemon, error} = state;

React.useEffect(() => {
if (!pokemonName) {
return
}
setState({status: 'pending'})
fetchPokemon(pokemonName).then(
pokemon => {
setState({status: 'resolved', pokemon})
},
).catch((error) => {
setState({status: 'rejected', error})
});

}, [pokemonName]);

if (status === 'rejected') throw error;

if (status === 'idle') {
return 'Submit a pokemon'
} else if (status === 'pending') {
return <PokemonInfoFallback name={pokemonName} />
} else if (status === 'resolved') {
return <PokemonDataView pokemon={pokemon} />
}
}

function ErrorFallback({error, resetErrorBoundary}) {
return (
<div role="alert">
<p>Something went wrong:</p>
<pre>{error.message}</pre>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
)
}

function App() {
Expand All @@ -35,12 +61,22 @@ function App() {
setPokemonName(newPokemonName)
}

function handleReset() {
setPokemonName('');
}

return (
<div className="pokemon-info-app">
<PokemonForm pokemonName={pokemonName} onSubmit={handleSubmit} />
<hr />
<div className="pokemon-info">
<PokemonInfo pokemonName={pokemonName} />
<ErrorBoundary
FallbackComponent={ErrorFallback}
onReset={handleReset}
resetKeys={[pokemonName]}
>
<PokemonInfo pokemonName={pokemonName} />
</ErrorBoundary>
</div>
</div>
)
Expand Down