1

This is my reducer for a snake game I'm making. Basically, whenever I want to reset the game, I update the state to INITIAL_STATE as seen in NEW_GAME, but whenever MOVE_SNAKE fires, it seems to be modifying INITIAL_STATE, so I'm basically passing it the current state and NEW_GAME does nothing.

I added that console.log(INITIAL_STATE.coords[0]) to confirm, and any time the snake moves, the INITIAL_STATE updates to the current state too. Why is this? I've done something similar like this in a tic tac toe game, but now it's not working?

// REDUCER

const INITIAL_STATE = {
    coords: [
        [1, 0],
        [1, 1],
        [1, 2]
    ]
};

export default function(state = INITIAL_STATE, action) {
    console.log(INITIAL_STATE.coords[0]);
    switch(action.type) {
        case 'MOVE_SNAKE':
            return {
                ...state,
                coords: action.coords
            }

        case 'NEW_GAME':
            return INITIAL_STATE;
    }

    return state;
}

// ACTION CREATORS

export function moveSnake(snake) {
    let { coords, direction } = snake;
    let headCoords = coords[coords.length-1];
    let newHead = () => {
        if(direction === 'DOWN') return [headCoords[0], headCoords[1]+1];
        if(direction === 'UP') return [headCoords[0], headCoords[1]-1];
        if(direction === 'LEFT') return [headCoords[0]-1, headCoords[1]];
        if(direction === 'RIGHT') return [headCoords[0]+1, headCoords[1]];
    };
    coords.push(newHead());
    coords.shift();

    return {
        type: 'MOVE_SNAKE',
        coords
    }
}

// COMPONENT CALL LOOKS LIKE THIS

this.props.moveSnake(this.props.snake);

I've tried using Object.assign() on everything, and it still was messing with my INITIAL_STATE.

user1807782
  • 451
  • 1
  • 4
  • 17
  • Can you paste any other code that uses this state, like action creators and selectors? How do you put together the new coords for the `MOVE_SNAKE` action? – markerikson Jan 20 '17 at 22:20
  • @markerikson added the action creator and the call! – user1807782 Jan 20 '17 at 22:29
  • Here is the answer by one of the creators of redux(Dan Abramov) : http://stackoverflow.com/questions/35622588/how-to-reset-the-state-of-a-redux-store – AlexB Jan 21 '17 at 04:20

1 Answers1

3

Your mutating the state, Object.assign() is good, but when working with arrays you should use concat, slice and filter!

Let's say you have an array

let a = {name:"bob", things: [1,2,4]}
let b = Object.assign({}, a, {name: "joe"})

In the example above you might be thinking that b is independent from a, but if we do something like b.things.push(3), you'll see that a.things changed!! To stop this, make sure you're using slice like this b.things = a.things.slice(). Hope this cleared it out ;)

Now, you're code is kinda hard to figure it out, but you know where you're working with and assigning arrays, so make sure you're using slice() as well, not only Object.assign().

Razvan Alex
  • 1,706
  • 2
  • 18
  • 21
  • I NEVER KNEW THAT! It works now, thank you! I should really start using Immutable or something. – user1807782 Jan 20 '17 at 22:50
  • Wow, amazing to hear this! This is the video that helped me understand it https://www.youtube.com/watch?v=9M-r8p9ey8U – Razvan Alex Jan 20 '17 at 22:56
  • Yup, as I figured. You should read the ["Structuring Reducers"](http://redux.js.org/docs/recipes/StructuringReducers.html) section of the Redux docs for more info, especially ["Prerequisite Concepts"](http://redux.js.org/docs/recipes/reducers/PrerequisiteConcepts.html) and ["Immutable Update Patterns"](http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html). – markerikson Jan 20 '17 at 23:20