Javascript 在React应用程序中更新动态呈现的元素时出现问题
我受够了。创建connect 4游戏时,我被困在需要更新所选单元格的部分 基于此代码,它的行为如何Javascript 在React应用程序中更新动态呈现的元素时出现问题,javascript,html,reactjs,Javascript,Html,Reactjs,我受够了。创建connect 4游戏时,我被困在需要更新所选单元格的部分 基于此代码,它的行为如何 只有从左上到右的对角线单元格显示一个红色圆圈,但它忽略了它的容器div HTML和CSS。它只占了那个div的空间 其他单元格根本不显示红色圆圈 如果我在点击其中一个产生红色圆圈的单元格后点击任意位置,就会出现错误“UncaughtTypeError:无法读取undefined的属性'key'” 如果在单击“非循环生成”单元格后单击任何单元格,控制台日志会将其添加到数组的末尾 错误: undefi
undefined: {$$typeof: Symbol(react.element), type: "div", key: "06", ref: null, props: {…}, …}
createBoards=()=>{
让gameBoard=[]
for(设i=0;i<6;i++){
游戏板[i]=[]
对于(设j=0;j<7;j++){
游戏板[i]。推(
这个.playerMove(e)}>
)
}
}
这是我的国家({
游戏板:游戏板
},函数(){
console.log(this.state.gameBoard)
})
}
playerMove=(e)=>{
让copyUserBoard=[…this.state.gameBoard]
设id=e.target.id
设i=e.target.id.split(“”).map(编号)
let element=copyUserBoard[i[0][i[1]].props.children
让clonedElement=React.cloneElement(
元素,
{className:“red”,key:id}
)
for(设i=0;i<6;i++){
对于(设j=0;j<7;j++){
if(id==copyUserBoard[i][j].key){
让newArr=Object.assign([],copyUserBoard,{[[i][j]]:clonedElement})
这是我的国家({
游戏板:纽瓦尔
})
console.log(this.state.gameBoard)
}
}
}
}
我建议您独立于DOM维护板的状态。下面是一个你可以如何做的例子。如果您有问题或任何需要澄清的地方,请告诉我
(我知道这不是connect four的工作原理。关键不是游戏机制,而是反应状态管理。)
//要渲染多少块板
const NUM_BOARDS=3;
//行数和列数
施工板尺寸=5;
//已占用单元格的值,
//也用作css类
常数PLAYER_1='p1';
常数PLAYER_2='p2';
//为方便起见,请交替播放
常量玩家=[PLAYER_1,PLAYER_2];
//板上一行的反应组件。
//props.cells-一组对象,每个对象具有
//一个值为PLAYER_1的“value”属性,
//PLAYER_2,或null
//props.onCellClick-用于
//告诉董事会某个特定单元格被点击。
常量行=({cells,onCellClick})=>(
{
cells.map(({value},index)=>(
- onCellClick(索引)}
className={'cell${value==null?'empty':PLAYERS[value]}`>
))
}
)
类板扩展React.Component{
建造师(道具){
超级(道具);
此.state={
玩家:0,
行:数组。from({length:BOARD_SIZE},()=>({
单元格:数组.from({length:BOARD_SIZE},()=>({value:null}))
}))
};
}
onCellClick=(行、单元格)=>{
const{rows,player}=this.state;
行[行]。单元格[单元格]={value:player};
这是我的国家({
行:[……行],
玩家:(玩家+1)%2,
})
}
渲染(){
const{rows}=this.state;
返回(
{rows.map((row,rowIndex)=>(
- this.onCellClick(rowIndex,cellIndex)}cells={row.cells}/>
))}
);
}
}
类ConnectFour扩展了React.Component{
render(){
返回(
{
//发射板
Array.from({length:NUM_BOARDS}).map({uu,i)=>(
))
}
)
}
}
ReactDOM.render(,document.querySelector(#app))
正文{
填充:20px;
}
李先生{
填充:0;
保证金:0;
列表样式:无;
}
#应用程序{
背景:#fff;
边界半径:4px;
填充:20px;
过渡:均为0.2s;
}
.董事会{
--尺寸:40px;
填充:10px;
保证金:10px自动;;
}
.行{
显示器:flex;
证明内容:中心;
高度:var(--大小);
}
.行.单元格{
弹性:0变量(--大小);
保证金:1px;
}
.row>.empty{
背景:#ccc;
}
.row>.cell.p1{
背景:红色;
边界半径:50%
}
.row>.cell.p2{
背景:蓝色;
边界半径:50%
}
我建议您独立于DOM维护板的状态。我会试着用一个例子来说明我的意思,并在一分钟内发布。@ray hatfield谢谢!期待它;)我没有忘记,但我需要离开一会儿。我回来后会收拾东西的。抱歉耽搁了。谢谢你这么做!昨天我接受了你的建议,开始做一些改变,但这里有一些好东西我需要从快乐帮助中学到。这里的关键思想是DOM是状态的表示,而不是状态本身。
createBoards = () => {
let gameBoard = []
for (let i = 0; i < 6; i++) {
gameBoard[i] = []
for (let j = 0; j < 7; j++) {
gameBoard[i].push(
<div className="box" key={[i]+[j]}>
<div
className="black"
id={[i]+[j]}
onClick={ (e) => this.playerMove(e)}>
</div>
</div>
)
}
}
this.setState({
gameBoard: gameBoard
}, function () {
console.log(this.state.gameBoard)
})
}
playerMove = (e) => {
let copyUserBoard = [...this.state.gameBoard]
let id = e.target.id
let i = e.target.id.split('').map(Number)
let element = copyUserBoard[i[0]][i[1]].props.children
let clonedElement = React.cloneElement(
element,
{ className: "red", key: id }
)
for (let i = 0; i < 6; i++) {
for (let j = 0; j < 7; j++) {
if (id === copyUserBoard[i][j].key) {
let newArr = Object.assign([], copyUserBoard, {[[i][j]]: clonedElement})
this.setState({
gameBoard: newArr
})
console.log(this.state.gameBoard)
}
}
}
}