Utilizing ReactJS useState to eliminate a className

Basically, I'm trying to remove a className from an element when a button is clicked. I've attempted to use useState hooks and a regular function, with the onClick event on the button triggering this function/setUseState. However, the className list remains unchanged. Below is a snippet of my code:

    function TileBoard() {
    
        const [openTileVisible, setOpenTileVisible] = useState(true);
        const [shuffler, setShuffler] = useState(0);
        const yellowTileIds = [9, 10, 11, 12, 15, 23, 24, 25, 33, 36, 37, 38, 39];
    
        let initialTiles = [];
    
        for (let i = 0; i <= 48; i++) {
            if (i === 48) {
                initialTiles.push(<Tile key={i} number={i} id={'openTile'} className={openTileVisible ? 'tile-black tile' : 'tile'}/>);
            } else {
                if (yellowTileIds.includes(i)) {
                    initialTiles.push(<Tile key={i} number={i} className={'tile-yellow tile'}/>);
                } else {
                    initialTiles.push(<Tile key={i} number={i} className={'tile-black tile'}/>);
                }
            }
        }
    
        const [tiles, setTiles] = useState(initialTiles);

    return (
      <div className={'game'}>
          <div key={shuffler} className={'board'}>
              <div className={'tiles'}>
                  {tiles}
              </div>
          </div>
          <button onClick={() => {
               setOpenTileVisible(false);
               shuffleArray();
          }}>SHUFFLE</button>
      </div>
    );
}

Despite changing the useState, the class isn't being removed. Am I making a mistake with the className attribute during object creation?

And here's the shuffle method:

function shuffleArray() {
        let array = tiles;
        for (let i = array.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            const temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        console.log(array);

        setTiles(array);
        // Forcing a Rerender since React doesn't recognize changes in element order in the array as a reason to rerender.
        setShuffler(shuffler + 1);
    }

Answer №1

Consider updating the computed value of tiles using useMemo instead of storing it in state. This ensures that the value is refreshed whenever the dependencies change.

import React, { useMemo } from "react";
const tiles = useMemo(() => {
  const tiles = [];

  for (let i = 0; i <= 48; i++) {
    if (i === 48) {
      tiles.push(
        <Tile
          key={i}
          number={i}
          id={"openTile"}
          className={openTileVisible ? "tile-black tile" : "tile"}
        />
      );
    } else {
      if (tiles.includes(i)) {
        tiles.push(
          <Tile key={i} number={i} className={"tile-yellow tile"} />
        );
      } else {
        tiles.push(<Tile key={i} number={i} className={"tile-black tile"} />);
      }
    }
  }
  return tiles;
}, [openTileVisible, shuffler]);

Answer №2

let newTilesArray = tiles;

By assigning the newTilesArray variable to the existing tiles array, we are not following the immutability principle in React.

Instead, I recommend using React.cloneElement() to make copies of your tile components, ensuring that the tiles re-render correctly.

You can update the code as shown below:

function shuffleArray() {
        let newArray = [...tiles]; //create a new array for tiles
        for (let i = newArray.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            const temp = newArray[i];
            newArray[i] = React.cloneElement(newArray[j]); //make a copy of the tile
            newArray[j] = React.cloneElement(temp); //make a copy of the tile
        }
        console.log(newArray);

        setTiles(newArray);
        //setShuffler(shuffler + 1); //no longer needed since the array modifications trigger re-renders
    }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can lazy loading of tabs be disabled in React Material UI?

I am currently working on implementing react tabs using the example provided on Material UI's website: https://material-ui.com/components/tabs/. However, I am facing an issue where my tabs are lazily loading the linegraph components instead of execut ...

"Encountering an unidentified custom element in Vue 2 while exploring Vue libraries

In my Vue project, I have integrated libraries like FusionCharts and VueProgressBar. However, I encountered an error in my console: Unknown custom element: <vue-progress-bar> - did you register the component correctly? For recursive components, make ...

Reactjs is currently not integrated with Firebase

I recently completed a project in reactjs and realized it requires authentication. My initial thought was to connect it with Firebase as it seemed like the most straightforward option. Following a tutorial on YouTube, however, I encountered some difficult ...

Tips for avoiding Navbar dropdowns covering other content

Using bootstrap 4 for a project and experiencing an issue with the navbar overlapping the content. How do I make the remaining content adjust when toggling the dropdown menu? To address this problem, I have applied a 50px margin to the body element. The ...

What is the best method to access an element with Vue.js?

I currently have a form set up like this <form v-on:submit.prevent="save_data(this)"></form> and a method defined in Vue.js like this methods: { save_data: function(f){ } } In jQuery, we can access the form using $(f)[0] My question ...

Mean stack authentication issue: missing token

Overview: Currently, I'm in the process of developing an application that utilizes node/express for the backend, mongo as the database, and angular for the frontend. User authentication is handled through jsonwebtoken, where a token is stored in local ...

What is the process for adding submitted data to an already-existing local JSON file?

I have a new Angular assignment that requires me to push form data into an existing JSON file locally. The task is to develop an Angular application where users can create new tasks and view them on a separate page. Initially, I attempted using http.post ...

"Receiving error message claiming no recipients are defined, despite the fact that my entered email address is

I recently followed a tutorial on implementing email functionality using Node.js, React.js, Nodemailer, and OAuth2. You can find the tutorial here. Despite entering the user's email correctly and confirming it with console logs in both the server and ...

Deleting with Axios and Express.js results in a 404 error when using parameters

I was anticipating the delete request const userDeleteHandler = (id: number) => { axios.delete('/admin/deleteUser/', {params: {UserID: id}}) .then(response => { console.log(response); }) .catch(error => { consol ...

Change the hover effects on the desktop to be more mobile-friendly

In my desktop version, I have implemented some code that enables hovering over a button to display additional information or text. How can I modify this for mobile so that nothing happens when the button is tapped on? .credit:hover .credit-text, .credit- ...

I ran npm install -f without any issues. However, when trying to deploy the application on Netlify or Vercel, the build logs are showing errors. I would appreciate any suggestions on how

Currently, I am using mui/styles, emotion/styled, and emotion/react which have specific requirements when it comes to React versions. The first set of libraries require a React version that is less than or equal to 16.8.0, while Next.js v13 requires a Re ...

Running the command "npm start" is resulting in an error message stating: "ENOENT: no such file or directory ... package.json"

After successfully creating a React app using NPX, I encountered an issue when trying to run npm start. The error message that appeared is as follows: $ npm start npm ERR! code ENOENT npm ERR! syscall open npm ERR! path C:\Users\Administrateur.TE ...

One function in Typescript lodash is missing a default export

Is there a way to import just one function from lodash? I attempted it like this: import get from 'lodash/get'; Even after installing both lodash and @types/lodash, I encountered the following error message: @types/lodash/get/index"' ha ...

Error encountered when trying to update Express Mongoose due to duplicate key

In my MongoDB database, I have a unique field called mail. When attempting to update a user, I encounter an issue where if I do not change the mail field, it triggers a duplicate key error. I need a solution where it is not mandatory to always modify the ...

Data retrieval error, function returned instead of expected value

Hey everyone, I'm currently working on fetching data using the GET method and I would like the data to be displayed after clicking a button, following standard CRUD operations. As a beginner in programming, I could use some help. Any assistance is gre ...

Unlock the Power of Core 2 MVC with the Cutting-edge Integration of

Looking for a solution on how to effectively use JQuery Datatables with Core MVC? Check out this helpful resource: Using jQuery DataTables Grid With ASP.NET CORE MVC I recently downloaded the sample project and made some modifications to fit my needs. It ...

The build process encountered an error due to the absence of ESLint configuration after the import

Having recently worked on a Vue project created using Vue CLI, I found that eslint was also included in the project. Although I haven't utilized eslint much up to this point, I understand that it is beneficial for catching stylistic errors, semantic e ...

Is it possible for Express JS to receive incoming requests from external sources and then transmit the retrieved data to the front end of

I am currently developing a React JS frontend for my application, but I have an interesting idea to incorporate an external mobile app that can control certain elements on the screen, such as font styles. To achieve this functionality, I require the web ap ...

When attempting to create a react app, I encounter difficulties using the npx create-react-app command

view image here I've attempted various solutions to fix the issue, such as deleting and reinstalling the node, but no matter what I do, it always ends up like this. I also tried removing node modules and reinstalling React, yet the problem persists. ...

Is it possible to compile a TypeScript file with webpack independently of a Vue application?

In my Vue 3 + Typescript app, using `npm run build` compiles the app into the `dist` folder for deployment. I have a web worker typescript file that I want to compile separately so it ends up in the root of the `dist` folder as `worker.js`. Here's wha ...