Skip to content

Problem with "Pygame Powered" section #40

@Hammad-hab

Description

@Hammad-hab
Image

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)
    } 
  }
 // ..rest

which 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;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions