Skip to content

Commit

Permalink
[hierarchical-state] Show the fetch count (and illustrate the dou…
Browse files Browse the repository at this point in the history
…ble fetching problem)
  • Loading branch information
dgroomes committed Jan 15, 2024
1 parent 0088dd4 commit bc43c62
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 12 deletions.
4 changes: 4 additions & 0 deletions hierarchical-state/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ General clean-ups, todos and things I wish to implement for this project:
something.
* DONE. Turn the "lucky numbers" component into a "dice roll" component. This component will fetch from a mock
HTTP/JSON API using the mocked fetch, and it will show the roll value and have a re-roll button.
* DONE (pretty decent; this shows the double fetching problem) Show the fetch count. I tried abstracting a GameApiClientClient and other things but the demo was getting
out of scope. I think I want like a global fetchCount state or something. Should I set it via props or use the Context API?
* Fix the double fetching problem. I think I need to push state up out of the GameDieRoll component. Not really sure.
I'm hoping to find multiple ways to solve this problem.
## Reference
Expand Down
2 changes: 1 addition & 1 deletion hierarchical-state/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
"esbuild": "~0.19.11"
},
"scripts": {
"start": "esbuild src/app.jsx --servedir=www --outdir=www/js --bundle --serve=[::1]:8000"
"start": "esbuild src/index.jsx --servedir=www --outdir=www/js --bundle --serve=[::1]:8000"
}
}
20 changes: 11 additions & 9 deletions hierarchical-state/src/GameDieRoll.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,24 +57,26 @@ const loadingDieAsciiArt = `
/**
* A game die ("die" as in dice 🎲). It can be re-rolled by clicking a button.
*/
export function GameDieRoll() {
console.log("[DiceRoll] Render function invoked.");
const [diceRoll, setDiceRoll] = useState(null);
export function GameDieRoll(props) {
console.log("[GameDieRoll] Render function invoked.");
const [gameDieRoll, setGameDieRoll] = useState(null);
const [isLoading, setIsLoading] = useState(true);

// This isn't right, I can't use this as a click handler because it basically makes a fetch outside of a useEffect
// callback, right? Again, I'm not sure how to do basic React programming.
const rollDice = () => {
props.incrementFetchCount();
setIsLoading(true);
console.log("[DiceRoll] `useEffect` callback invoked. Making a 'fetch' request.");
console.log("[GameDieRoll] `useEffect` callback invoked. Making a 'fetch' request.");
fetch('/dice-roll')
.then(response => {
console.log("[DiceRoll] `fetch` received a response.");
console.log("[GameDieRoll] `fetch` received a response.");
return response.json();
})
.then(data => {
setDiceRoll(data);
setGameDieRoll(data);
setIsLoading(false);
})
.catch(error => console.error('Unexpected error during fetch', error));
});
};

useEffect(rollDice, []); // Empty dependency array ensures this runs once on mount and not on every render
Expand All @@ -90,7 +92,7 @@ export function GameDieRoll() {

return (
<div className="game-die-roll">
<pre className="game-die-roll-art">{gameDieNumberToAsciiArt[diceRoll]}</pre>
<pre className="game-die-roll-art">{gameDieNumberToAsciiArt[gameDieRoll]}</pre>
<button onClick={rollDice}>Re-roll</button>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,25 @@ import { GameDieRoll } from './GameDieRoll';

function App() {
const [diceCount, setDiceCount] = useState(1);
const [fetchCount, setFetchCount] = useState(0);

const addGameDieRoll = useCallback(() => {
setDiceCount(diceCount + 1);
}, [diceCount]);

const incrementFetchCount = useCallback(() => {
setFetchCount(i => i + 1);
}, []);

const dice = [];
for (let i = 0; i < diceCount; i++) {
dice.push(<GameDieRoll key={i}/>);
dice.push(<GameDieRoll key={i} incrementFetchCount={incrementFetchCount}/>); // How does this work? When a property changes what does React do? I'm not even asking the question clearly.
}

return (
<>
<button onClick={addGameDieRoll}>Add another roll 🎲</button>
<div className={"statistics"}>The <pre>fetch</pre> function has been called {fetchCount} times</div>
<hr/>
{dice}
</>
Expand Down
2 changes: 1 addition & 1 deletion hierarchical-state/www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ <h1>react-playground/hierarchical-state</h1>
<div id="root"></div>

<!-- The 'js/app.js' file is a generated file -->
<script src="js/app.js"></script>
<script src="js/index.js"></script>

</body>
</html>
9 changes: 9 additions & 0 deletions hierarchical-state/www/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,12 @@
font-family: monospace;
line-height: 1;
}

.statistics {
margin: 20px;
display: inline-block;

& * {
display: inline-block;
}
}

0 comments on commit bc43c62

Please sign in to comment.