-
-
Notifications
You must be signed in to change notification settings - Fork 11
Description
The powered by pygame section of the home page exhibits a strange issue where, upon load, the page shows the same image for two or more games. This behavior is being caused by the usage of data-info for storing data in the DOM. In NextJS it is not only inconvinent, but also impractical and unpredictable to use the DOM for storing data.
Instead, one could create a decorator which returned a unique event handler for different IDs.
Likewise:
// ... constructor ...
changeBackground(e: any, id: number) {
this.setState({ currentGameId: id });
}
changeBackgroundForSpecificID (id: number) { // decorator, returns a different event handler for different elements
return (e: any) => {
this.changeBackground(e, id)
}
}
// ..restwhich can be used as follows:
<div className={styles.poweredcards}>
{games.map((data, key) => {
return (
<div key={key} onMouseEnter={this.changeBackgroundForSpecificID(key)} data-info={key}>
<PoweredCard name={data.name} author={data.author} link={data.mainlink} />
</div>
);
})}
</div>This not only mitigates the issue but also eliminates the need for these two conditions at the top of the component
if (this.state.currentGameId === undefined) {
this.setState({ currentGameId: 0 });
}
var currentGame = games[this.state.currentGameId];
if (currentGame === undefined) {
currentGame = games[0];
console.log(this.state.currentGameId)
}In the future, application state should not be stored in data-* attributes. React mechanisms (props, state, or closures) should be used instead, as they are predictable under both SSR and client-side rendering
Finally, the inconsistent usage of function and class components in the codebase is confusing and counter-productive so powered.tsx could be refactored into a component which uses the modern function components.
import React, { useState, useCallback } from 'react';
import Head from 'next/head';
import styles from '@/styles/powered.module.css';
import drawnDownAbyss1 from '@/assets/drawn-down-abyss-1.png';
import froggo1 from '@/assets/froggo-swing-n-grapple-1.png';
import resync1 from '@/assets/resync-1.png';
import tuxemon1 from '@/assets/tuxemon-1.png';
import PoweredCard from './powered-card';
// data goes here... games
const Powered: React.FC = () => {
const [currentGameId, setCurrentGameId] = useState(0);
const changeBackground = useCallback((id: number) => {
setCurrentGameId(id);
}, []);
const currentGame = games[currentGameId];
return (
<>
<Head>
{games.map((data, key) => (
<link key={key} rel="preload" href={data.image} as="image" />
))}
</Head>
<div
className={styles.powered}
style={{
backgroundImage: `url(${currentGame.image})`,
}}
>
<div className={styles.poweredcontainer}>
<div className={styles.header}>Pygame Powered</div>
Over the many years pygame has been around, there have been amazing projects created by the community.
<div className={styles.poweredcards}>
{games.map((data, key) => (
<div
key={key}
onMouseEnter={() => changeBackground(key)}
data-info={key}
>
<PoweredCard
name={data.name}
author={data.author}
link={data.mainlink}
/>
</div>
))}
</div>
</div>
</div>
</>
);
};
export default Powered;