RRP
RRP

Reputation: 2853

Render a container based on logic React/Redux

I have two containers in my App.js and the state is maintained in the Redux store.

 <StartGameContainer/>
 <GameContainer/>

The state of my app has a property called "gameStatus" which is set to false. I am trying to use this property to render my component in GameContainer if true. This property is set to true when I click a Start button in my StartGameContainer.

When the App initially renders it notices that this property is false. When I click on the start button it has no effect in rendering the contents from GameContainer. How can I achieve this or have gotten this layout wrong?

EDIT

GameContainer.js

const mapStateToProps = state => (
    {
        board: state.boardGame.board,
        gameStatus: state.boardGame.gameStatus
    }
);

const mapDispatchToProps = dispatch => {
    return {
        initGame: () => {
            dispatch(allActions.initGame())
        },

        selectCol : (val) => {
            dispatch(allActions.dropTile(val))
        }
    }
};

const GameContainer = connect(mapStateToProps, mapDispatchToProps)(GridCells);

class GridCells extends Component {

    componentDidMount() {
        this.props.initGame();
    }

    render() {
        if(this.props.gameStatus){
            return (
                <div className="game">
                    <table>
                        <thead>
                        </thead>
                        <tbody>
                        {this.props.board.map((row, i) => (
                            <RowCells key={i} row={row} select={this.props.selectCol}/>
                        ))}
                        </tbody>
                    </table>
                </div>
            )
        }else{
            return(<div></div>)
        }
    }
}

StartGameContainer.js

const mapDispatchToProps = dispatch => {
    return{
        pickPlayer: (currPlayer) => {
            dispatch(allActions.setPlayer(currPlayer))
        }
    }
};
const StartGameContainer = connect(null, mapDispatchToProps)(StartGame);


class StartGame extends Component{
    constructor(props){
        super(props);
        this.players = ['myself', 'service'];
        this.selectedVal = 1;
    }

    selectedPlayer(event){
        this.selectedVal = event.target.value === 'myself' ? 1 : 2;
    }

    render(){
        let options = this.players.map((val) => {
            return (<option key={val} value={val}>{val}</option>)
        });
        return(
            <div className='startGame'>
                <select name="players" id="players" onChange={this.selectedPlayer.bind(this)}>
                    {options}
                </select>
                <button onClick= {() => {this.props.pickPlayer(this.selectedVal)}}>Start Game</button>
            </div>
        )
    }
}

Upvotes: 2

Views: 178

Answers (1)

Cumulo Nimbus
Cumulo Nimbus

Reputation: 9695

Not entirely sure what your Redux logic looks like... but betting your problems arise from a misunderstanding of how hoisting works.

Try putting both your connect code lines below the class definitions:

class StartGame extends Component{ ... }

const StartGameContainer = connect(null, mapDispatchToProps)(StartGame)

Check out this SO answer about how JS classes are hoisted but not initialized.

"It's never a good idea to use a class before its definition"

Here's a simplified example to help you better understand why your code is not throwing an error, but also not working properly. Consider this snippet:

function logYourClass() {
  console.log(yourClass)
  var yourClass = 'all the class details'
}
logYourClass()

If you run this you'll notice undefined gets logged, and there is no "yourClass is not defined" ReferenceError thrown. This is because the above code is equivalent to writing:

function logYourClass() {
  var yourClass
  console.log(yourClass)
  yourClass = 'all the class details'
}
logYourClass()

Also worth noting that ES6 let and const declaration are not hoisted. Try replacing the var in the above code with either one of these keywords and you'll see an Uncaught ReferenceError.

function logYourClass() {
  console.log(yourClass)
  const yourClass = 'all the class details'
}
logYourClass()

Upvotes: 2

Related Questions