Redux action throwing "TypeError: Cannot read property 'num_of_players' of undefined" in mapStateToProps function

Redux action throwing "TypeError: Cannot read property 'num_of_players' of undefined" in mapStateToProps function

我是 react/redux 的新手,正在尝试构建一个掷骰子游戏。我在 PregameContainer 中定义了 mapStateToProps,因为我希望用户能够 select 玩家数量和玩家名称,然后在游戏期间将其映射到子组件的道具。但是,当我尝试使用游戏按钮更改商店中的状态时,它会抛出错误:

我知道 mapStateToProps 函数将在商店数据更改时被调用。我不明白的是为什么状态第二次为空。

这是我的一些文件。了解我对这个框架非常陌生,而且我确信我没有把东西放在正确的地方。任何帮助将不胜感激。

#PregameContainer.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import PregameInput from './PregameInput'
import Game from '../Game'

class PregameContainer extends Component {
    

   render(){
    return (
        <div>
            {this.props.isSubmitted === false && <PregameInput submit={this.props.submit}/>}
            {this.props.isSubmitted && <Game settings={this.props}/>}
          
        </div>
        )
    }
}

const mapStateToProps = state => ({ 
    num_of_players: state.num_of_players, 
    p1: state.p1, 
    p2: state.p2, 
    p3: state.p3, 
    p4: state.p4, 
    isSubmitted: state.isSubmitted, 
     })

const mapDispatchToProps = dispatch => ({
  submit: game => dispatch({type: 'SUBMIT', game}),
  roll: roll => dispatch({type: 'ROLL', roll}),
  keep: keep => dispatch({type: 'KEEP', keep}),
  end: end => dispatch({type: 'END', end}),
})

export default connect(mapStateToProps, mapDispatchToProps)(PregameContainer)
#Game.js
import React, { Component } from 'react';
import { connect } from 'react-redux'
import Score from './scoreboard/Score'
import PlayerKeep from './table/board/PlayerKeep'
import RollBoard from './table/board/RollBoard'
import ButtonsContainer from './table/board/ButtonsContainer'

class Game extends Component{
constructor(props) {
    super(props);
    this.state = {
        }
    }
    player(){ let x
        if (this.props.current_player === 1) x = this.props.settings.p1
        else if(this.props.current_player === 2) x = this.props.settings.p2
        else if(this.props.current_player === 3) x = this.props.settings.p3
        else x = this.props.settings.p4
        return x;
    }

    render()
    {
    return (
        <div className="game_container">
               <div>
            <div className="board_container">  
            <h4 > {this.player()}'s Turn!</h4>
            <h6 className="turn">TURN {this.props.current_turn} </h6>
            <br></br><br></br>
            <RollBoard settings={this.props}/>
            <br></br>
            <PlayerKeep settings={this.props}/>
            <ButtonsContainer settings={this.props}/>
        </div>
    </div>
                <Score settings={this.props.settings}/>
            </div>
    )
    }
}

    const mapStateToProps = state => ({p1_score: 0,
        p2_score: 0, 
        p3_score: 0, 
        p4_score: 0, 
        current_player: 1,
        current_turn: 1,
        keep_value: 0,
        rollable_dice: 6,
        rolled_dice: [],
        kept_dice: [],
        selected_value: 0,
    })


    

    
    export default connect(mapStateToProps)(Game) 
#manageGame.js (reducer)
export default function manageGame(state = {
    p1_score: 0,
    p2_score: 0, 
    p3_score: 0, 
    p4_score: 0, 
    current_player: 1,
    current_turn: 1,
    keep_value: 0,
    rollable_dice: 6,
    kept_dice: [],
    rolled_dice: [],
    selected_value: 0,
    p1:"Player 1",
    p2:"Player 2",
    p3:"Player 3",
    p4:"Player 4",
    num_of_players: 2,
    isSubmitted: false

    }, action) {

      switch (action.type) {

      case 'SUBMIT':
          const settings = { game: action.game };
          return {
            ...state,
            p1: settings.game.p1, 
            p2: settings.game.p2,
            p3: settings.game.p3,
            p4: settings.game.p4,
            num_of_players: settings.game.num_of_players,
            isSubmitted: true
            }

      case 'ROLL':
          return {
            ...state,
            rolled_dice: Array.from({length: state.rollable_dice}, () => Math.floor(Math.random() * 6))
            }, console.log(state);
            
           
  
        case 'KEEP':
          const keep = { game: action.keep };

          return{

        };

        case 'END':
          const end = { game: action.end };

          return{
            ...state,

          };

        default:
          return state;
    
      }
    }

这就是引发错误的原因(“滚动”按钮)-

import React, { Component } from 'react';
import { connect } from 'react-redux'

class GameButtons extends Component {

    constructor(props) {
        super(props);
};    




render(){
    return (
        <div>
            {console.log(this.props)}
            <button onClick={this.props.settings.settings.roll} className="game_buttons" >Roll Dice</button>
            <button onClick={this.props.keep} className="game_buttons">Keep Selected</button> 
            <button onClick={this.props.end} className="game_buttons">End Turn</button>
        </div>
    )
}
}



export default connect()(GameButtons)

你的减速器有一个错误。

case 'ROLL':
      return {
        ...state,
        rolled_dice: Array.from({length: state.rollable_dice}, () => Math.floor(Math.random() * 6))
        }, console.log(state);
        

return 表达式的计算结果为 undefined。问题是您无意中使用了 javascript 鲜为人知的 comma operator。 return 值将是逗号后的右侧值,即 console.log() 调用,始终为 undefined。这就是您收到此错误的原因,因为传递给 mapStateToProps 的 redux 状态现在是 undefined.

去掉逗号语句。 如果要写入控制台,请在 return 语句之前执行。

 case 'ROLL':
      console.log(state);
      return {
        ...state,
        rolled_dice: Array.from({length: state.rollable_dice}, () => Math.floor(Math.random() * 6))
        };

但最好让您的 reducer 函数保持纯净,并避免在您的 reducer 内部产生任何副作用(写入控制台是一种副作用)。您可以考虑使用 redux-logger 中间件代替 https://www.npmjs.com/package/redux-logger