简体   繁体   English

我想使用 React with hooks 随机化 css 类网格中的项目

[英]I want to randomize the css classes the items in a grid using React with hooks

I've created a grid component in React.我在 React 中创建了一个网格组件。 I have an array of strings named 'availableColors' in which I am storing the css class names I want to use.我有一个名为“availableColors”的字符串数组,其中存储了我要使用的 css class 名称。

In the 'RandomColorGrid' component I'm setting the initial colors of each grid item in 'useState', assigning an index from 'availableColors' to each item.在“RandomColorGrid”组件中,我设置了“useState”中每个网格项目的初始 colors,为每个项目分配了“availableColors”的索引。

Each item in the grid calls 'changeColors()' onClick. Inside that method I reassign the calue of each 'box' in 'colors' with a new randomly chosen index from 'availableColors'.网格中的每个项目都调用“changeColors()”onClick。在该方法中,我使用从“availableColors”中随机选择的新索引重新分配“颜色”中每个“框”的值。

This works well enough but feels a little clunky.这工作得很好,但感觉有点笨拙。 There are two things I am trying to improve but am getting stuck.有两件事我想改进,但卡住了。

First;第一的; I would like to use each color only once when the 'changeColors()' function is called.我只想在调用“changeColors()”function 时使用每种颜色一次。 Currently it's possible for the same color to be used on more than one grid item and I would like them to be four unique colours each time.目前,可以在多个网格项目上使用相同的颜色,我希望它们每次都是四种独特的颜色。

Second;第二; I would like for no item to be the same color twice in a row.我不希望任何物品连续两次出现相同的颜色。 So for any given item I would line to exclude that item's current color from the possible random choices.因此,对于任何给定的项目,我会从可能的随机选择中排除该项目的当前颜色。

I've been trying to achieve this by taking the color index of the current color and forming a new array of colors to randomly select from for each item and then another array to try and track the colors that have already been used in order to avoid duplicates but in doing so have gotten into a real mess.我一直在尝试通过获取当前颜色的颜色索引并为每个项目形成一个新的 colors 到随机 select 的新数组然后另一个数组来尝试跟踪已经使用的 colors 来实现这一点以避免重复但这样做已经陷入了真正的混乱。 This leads me to believe that my design is probably bad from the start.这让我相信我的设计可能从一开始就很糟糕。

How can I improve on this?我该如何改进呢?

import React, { useState } from "react";

const availableColors = ["red", "green", "blue", "yellow"];

const changeColors = (colors, setColors) => {
  colors.box1 = availableColors[randomNumber(colors.box1)];
  colors.box2 = availableColors[randomNumber(colors.box2)];
  colors.box3 = availableColors[randomNumber(colors.box3)];
  colors.box4 = availableColors[randomNumber(colors.box4)];
  setColors({ ...colors });
};

const randomNumber = (currentColour) => {
  let indices = [0, 1, 2, 3];
  indices.splice(availableColors.indexOf(currentColour), 1);
  return indices[Math.floor(Math.random() * indices.length)];
};

export const RandomColorGrid = () => {
  let [colors, setColors] = useState({
    box1: availableColors[0],
    box2: availableColors[1],
    box3: availableColors[2],
    box4: availableColors[3],
  });

  return (
    <div className="grid">
      <div
        className={`${colors.box1}`}
        onClick={() => changeColors(colors, setColors)}
      />
      <div
        className={`${colors.box2}`}
        onClick={() => changeColors(colors, setColors)}
      />
      <div
        className={`${colors.box3}`}
        onClick={() => changeColors(colors, setColors)}
      />
      <div
        className={`${colors.box4}`}
        onClick={() => changeColors(colors, setColors)}
      />
    </div>
  );
};

Your problems come from not respecting the immutability of objects.您的问题来自不尊重对象的不变性。 You change an object and rely on the object not changing in the next line (in changeColors)您更改 object 并依赖 object 在下一行中没有更改(在 changeColors 中)

The solution would be to copy new arrays of the available colors, and using.filter to make sure we dont repeat the same colors twice by replacing the new currentlyAvailableColors array to only include colors that are ok to use解决方案是复制可用 colors 的新 arrays,并使用 .filter 确保我们不会通过替换新的 currentlyAvailableColors 数组以仅包含可以使用的 colors 来重复相同的 colors 两次

const changeColors = (colors, setCurrentColours) => {
    const nextColors = {};
    let currentlyAvailableColors = [...availableColors];
    nextColors.box1 = getRandomOption(colors.box1, currentlyAvailableColors)
    currentlyAvailableColors = currentlyAvailableColors.filter(col => col !== nextColors.box1);
    
    nextColors.box2 = getRandomOption(colors.box2, currentlyAvailableColors)
    currentlyAvailableColors = currentlyAvailableColors.filter(col => col !== nextColors.box2);
    
    nextColors.box3 = getRandomOption(colors.box3, currentlyAvailableColors)
    currentlyAvailableColors = currentlyAvailableColors.filter(col => col !== nextColors.box3);
    
    nextColors.box4 = getRandomOption(colors.box4, currentlyAvailableColors)
    currentlyAvailableColors = currentlyAvailableColors.filter(col => col !== nextColors.box4);
    
    setCurrentColours({ ...nextColors });
  };

Heres a working codepen https://codepen.io/yftachman/pen/XWZMqVZ这是一个工作代码笔https://codepen.io/yftachman/pen/XWZMqVZ

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM