javascript - 如何动态更改 react 中动态片段的样式(使用功能组件)?

标签 javascript css reactjs

TLDR-我想更改 1 个正方形 onClick 的背景颜色。我不知道如何区分这 1 个方 block 和其他 63 个方 block ,因为它们是动态创建的

我正在动态创建一个由 64 个方 block 组成的棋盘,并且如果在适当的条件下(最好是在 selectPiece 函数下)选择方 block ,我希望方 block 的背景颜色能够改变,然后在进行移动或方 block 上的棋子后恢复回来未选中。我的问题是识别动态创建的方 block 以更改其状态。

Board.js

    let [squareStyle] = useState('squares ');

    function Row(i){
        const newRow = [];
        let count = i * 8;   
        let squareImp;     
        for (let j = 0; j<8; j++){            
            if ((i + j) % 2 === 1){                
                squareImp = squareStyle + "g";
            }else {
                squareImp = squareStyle + "y";
            }
                newRow.push(<div key={count} id={i * 10 + j} className={squareImp} onClick={isMove ? selectMove : props.data[count].name !== null ? selectPiece : undefined  }>
                     { (props.data[count].name != null) &&
                        <img src={images[props.data[count].name]}
                        className="icons"
                        alt="chess piece" />    
                    }
                </div>)            
            count++;
            
        }
        return <div className="rows" key={i}>{newRow}</div>;
    }

如果我使用基于类的组件,那么我可以使用 this.setState 来更改单个方 block ,使用类似 -

this.setState({className: "squares b"})

但是对于函数组件,setState 对于每个属性都是唯一的。因此,虽然我可以使用 id(当前未用于 CSS)来获取选定的方 block ,但我无法为每个方 block 创建一个 [state, setState] 变量。是否可以动态创建变量?又名类似

function setBackground(int id){
    let StateChange = id + ""
    setStateChange({backgroundColor:"blue"})

好像不是。

因此,在我花了相当多的时间阅读这里有关如何在 React 中动态更改 CSS 的大量帖子之后,我尝试遵循我认为可能适用于我的唯一一篇文章 - How to add a CSS class to an element on click - React并使用类似这样的函数设置 className -

Board.js

    function Row(i){
        const newRow = [];
        let count = i * 8; 
        for (let j = 0; j<8; j++){          
                newRow.push(<div key={count} id={i * 10 + j} className={getClassName(i, j)} onClick={isMove ? selectMove : props.data[count].name !== null ? selectPiece : undefined  }>
                     { (props.data[count].name != null) &&
                        <img src={images[props.data[count].name]}
                        className="icons"
                        alt="chess piece" />    
                    }
                </div>)            
            count++;
            
        }
        return <div className="rows" key={i}>{newRow}</div>;
    }
    //function getClassName(e, i, j){ //can't read e
    function getClassName(i, j){
        console.log(i, j)
        //console.log(e.currentTarget)
        let base = "squares ";
        if (clicked){
        // if (clicked && e.currentTarget.id == i * 10 + j){ //this is what I want but I can't figure out how to grab the target to compared the id to          
                 return base + "b";            
        } else {
             if ((i + j) % 2 === 1){                
                 return base + "g";
             }else {
                 return base + "y";
             }
        }
    }

但正如您可能从注释掉的文本中看出的那样,我不知道如何获取事件,因此使用 id 进行比较,这样我只更改所选方 block 的背景颜色而不是整个方 block 的背景颜色板。

我不明白事件处理的细微差别,但我猜测因为我是从 div 元素的 className 属性而不是元素本身调用该函数,所以该事件不可用。我不知道如何解决它。

如有任何帮助,我们将不胜感激

最佳答案

所以我会这样做。我将 Square 抽象为它自己的组件,它是通过 for 循环创建的。每个 Square 都可以管理自己的本地状态,因此当单击它们时,它们可以更新自己的状态,并且您不需要困惑的集中式代码。

仅供引用,您似乎错误地使用了useState,因为它确实有自己的函数来更新其本地状态。下面的代码不是 100% 正确,因为我不确定你在做什么,但它应该给你一个大概的轮廓。

我还会查看 React 文档:https://reactjs.org/docs/hooks-state.html

这样您就可以清楚地了解 useState Hook 及其使用方式。

const { useState } from 'react'

const Square = (i, j, data, count, isMove, selectMove) => {
    const [ squareStyle, setSquareStyle ] = useState('square') // then use setSquareStyle('STYLING) to update local state
    const selectedPiece = data[count].name
    return (
        <div key={count} 
        id={i * 10 + j} 
        className={getClassName(i, j)} 
        onClick={isMove ? selectMove : selectedPiece ? selectPiece : undefined  }>
        { (selectedPiece.name != null) &&
            <img src={images[props.data[count].name]}
                className="icons"
                alt="chess piece" />    
        }
        </div>
    )
}




function Row(i){
    const newRow = [];
    let count = i * 8; 
    for (let j = 0; j<8; j++){          
            newRow.push(
                <Square 
                    i={i} 
                    j={j} 
                    count={count} 
                    isMove={isMove} 
                    selectMove={selectMove} 
                />
            )            
        count++;
        
    }
    return <div className="rows" key={i}>{newRow}</div>;
}
//function getClassName(e, i, j){ //can't read e
function getClassName(i, j){
    console.log(i, j)
    //console.log(e.currentTarget)
    let base = "squares ";
    if (clicked){
    // if (clicked && e.currentTarget.id == i * 10 + j){ //this is what I want but I can't figure out how to grab the target to compared the id to          
             return base + "b";            
    } else {
         if ((i + j) % 2 === 1){                
             return base + "g";
         }else {
             return base + "y";
         }
    }
}

关于javascript - 如何动态更改 react 中动态片段的样式(使用功能组件)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64648645/

相关文章:

javascript - 同时触发的多个 ajax 调用无法正常工作

javascript - 允许html2canvas显示图片和下载图片

javascript - 强制整个网站使用一种字体系列

reactjs - 当我刷新页面时,Gatsby 链接状态丢失

reactjs - 使用 React 为 Leaflet 安装 Overlapping Marker Spiderfier

javascript - 在 Canvas 中拖动时图像闪烁

javascript - 如何通过 jQuery 从 JIRA REST API 获取和发布数据?

html - 视频背景网格叠加问题

javascript - Chrome 上的 jQuery fontSize 增加

node.js - 在 React 中使用 Apollo.js 将查询映射到 props