javascript - 为什么我的状态不能使用 Redux 正确改变?
问题描述
我做了一个井字游戏,用户与计算机。它在不使用 Redux 的情况下工作得非常好,但是自从将 Redux 纳入其中之后,事情就变得不对劲了。
我想要实现的是:如果有一个空方块,那么 CPU 会随机放置O
一个空位置(在用户放置一个 之后X
),但这次使用 Redux。
我觉得这let turnState = this.props.turnValueReducerRedux(this.state.turn);
是导致问题的原因和/或我的turnReducer.js
文件不正确。
我已经标记// START HERE
并// END HERE
指出我认为问题可能源于何处。
我做错了什么,我该如何解决?
这里是Board.js
import React, { Component } from 'react';
import './Board.css';
import { connect } from 'react-redux';
import * as actionTypes from '../../store/actions/actions';
class Board extends Component {
constructor(props) {
super(props);
this.state = {
winner: undefined,
};
this.gameState = {
turn: 'X',
gameLocked: false,
gameEnded: false,
board: Array(9).fill(''),
totalMoves: 0
}
this.clicked = this.clicked.bind(this);
}
clicked(box) {
if(this.gameState.gameEnded || this.gameState.gameLocked) {
return;
}
// START HERE
let turnState = this.props.turnValueReducerRedux(this.gameState.turn);
if(this.gameState.board[box.dataset.square] === '') {
this.gameState.board[box.dataset.square] = turnState;
box.innerText = this.gameState.turn;
this.gameState.turnState = this.gameState.turnState === 'X' ? 'O' : 'X';
this.gameState.totalMoves++;
}
// END HERE
console.log("this.gameState.totalMoves ==> " + this.gameState.totalMoves);
var result = this.checkWinner();
if(result === 'X') {
this.gameState.gameEnded = true;
this.setState({
winner: 'X',
winnerLine: 'X wins'
});
console.log("X wins");
} else if(result === 'O') {
this.gameState.gameEnded = true;
this.setState({
winner: 'O',
winnerLine: 'O wins'
});
console.log("O wins");
} else if(result === "draw") {
this.gameState.gameEnded = true;
this.setState({
winner: 'draw',
winnerLine: 'match is a draw'
});
}
console.log("result ==> " + result);
if(this.gameState.turnState === 'O' && !this.gameState.gameEnded) {
this.gameState.gameLocked = true;
setTimeout(() => {
do {
var random = Math.floor(Math.random() * 9);
} while(this.gameState.board[random] !== '');
this.gameState.gameLocked = false;
console.log("reached here");
this.clicked(document.querySelectorAll('.square')[random]);
}, 3000)
}
}
render() {
return(
<div id="game">
<div id="state">{this.state.winnerLine}</div>
<div id="head">
Tic Tac Toe
</div>
<div id="board" onClick={(e) => this.clicked(e.target)}>
<div className="square" data-square="0"></div>
<div className="square" data-square="1"></div>
<div className="square" data-square="2"></div>
<div className="square" data-square="3"></div>
<div className="square" data-square="4"></div>
<div className="square" data-square="5"></div>
<div className="square" data-square="6"></div>
<div className="square" data-square="7"></div>
<div className="square" data-square="8"></div>
</div>
</div>
);
}
}
const mapStateToProps = state => {
return {
turnValue: state.turnValue
};
};
const mapDispatchToProps = dispatch => {
return {
turnValueReducerRedux: (value) => dispatch({type: actionTypes.TURN_VALUE, value})
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Board);
这是turnReducer.js
:
import * as actionTypes from '../actions/actions';
const initialValue = {
turnValue: 'O'
};
const turnReducer = (state = initialValue, action) => {
switch (action.type) {
case actionTypes.TURN_VALUE:
console.log("turnReducer ==> " + action.value);
return {
...state,
turnValue: action.value
};
default:
return state;
}
}
export default turnReducer;
解决方案
我认为连接的调度操作 ( turnValueReducerRedux
) 不会返回您所期望的。它将返回完整的 action ({ type: '...', value: ... })
,而不仅仅是值,这意味着 turnState 在以下代码中不正确:
let turnState = this.props.turnValueReducerRedux(this.state.turn);
if(this.gameState.board[box.dataset.square] === '') {
this.gameState.board[box.dataset.square] = turnState;
作为一般建议,您似乎不依赖state
或存储来呈现数据,这是 Reacts 的主要职责之一。因此,您通过调度操作在商店中设置值,但从不使用 访问它this.state.turnValue
,这是由以下代码定义的:
const mapStateToProps = state => {
return {
turnValue: state.turnValue
};
};
还要注意gameState
和state
非常不同,因为后者会触发重新渲染并连接到商店,而前者不会。
更新
根据我们下面的讨论,这是一个采用不同方法的示例:https ://codesandbox.io/s/x2x773pqxz
自动计算机播放器是复杂的部分,因为这是人类播放器动作的副作用。因此,我添加redux-thunk
以允许某些操作触发其他操作。我已经延迟了计算机的转动,以便您可以看到它的运行情况。
我还将板子和各个 Squares 拆分为单独的组件,这两个组件都纯粹是为了展示。Game
组件和redux/actions.js
文件是最重要的。
从理论上讲,您可以选择您喜欢的任何棋盘大小和玩家数量,但 css 只是为 3x3 棋盘设置的。
我没有实现这个findWinner
逻辑,因为感觉太费劲了
让我知道是否可以澄清任何事情,希望对您有所帮助!
推荐阅读
- reference - 如何在参考 Vec 上使用生命周期?
- binary-decision-diagram - 多输出 BDD 的生成
- django - 渲染器返回 unicode,并且没有指定字符集值
- javascript - http响应后需要运行变量
- c++ - Sprite Texture没有从图像C ++中分割碎片
- java - 为什么 isPrime 使用 i*i < n 为除 2^31- 1 之外的每个 int 返回正确答案
- javascript - 如何在 amCharts 中显示饼图
- python - 带有 gunicorn 的日志记录模块
- bash - Bash 命令仅从该行返回搜索模式
- python - 有没有其他方法可以在列下方拆分?