6

I am trying to understand Redux online tutorials that are posted by Dan Abramov. At present I am on the following sample:

Reducer composition with Arrays

Here is my practice code following the above sample:

// Individual TODO Reducer
const todoReducer = (state, action) => {
    switch(action.type) {
    case 'ADD_TODO':
        return {
            id: action.id,
            text: action.text,
            completed: false
          };
    case 'TOGGLE_TODO':
        if (state.id != action.id) return state;

      // This not working
      /*
      return {
        ...state,
        completed: !state.completed
      };
      */

      //This works
      var newState = {id: state.id, text: state.text, completed: !state.completed};
      return newState;
    default:
        return state;
  }
};

//TODOS Reducer
const todos = (state = [], action) => {
        switch(action.type) {
        case 'ADD_TODO':
       return [
          ...state,
          todoReducer(null, action)
       ];
       case 'TOGGLE_TODO':
        return state.map(t => todoReducer(t, action));
      default:
        return state;
    }
};

//Test 1
const testAddTodo = () => {
  const stateBefore = [];

  const action = {
      type: 'ADD_TODO',
      id: 0,
      text: 'Learn Redux'
  };

  const stateAfter = [{
     id: 0,
     text: "Learn Redux",
     completed: false
  }];

  //Freeze
  deepFreeze(stateBefore);
  deepFreeze(action);

  // Test
  expect(
     todos(stateBefore, action)
  ).toEqual(stateAfter);
};

//Test 2
const testToggleTodo = () => {
  const stateBefore = [{id: 0,
     text: "Learn Redux",
     completed: false
  }, {
    id: 1,
    text: "Go Shopping",
    completed: false
  }];

  const action = {
      type: 'TOGGLE_TODO',
      id: 1
  };

  const stateAfter = [{
     id: 0,
     text: "Learn Redux",
     completed: false
  }, {
    id: 1,
    text: "Go Shopping",
    completed: true
  }];

  //Freeze
  deepFreeze(stateBefore);
  deepFreeze(action);

  // Expect
  expect(
     todos(stateBefore, action)
  ).toEqual(stateAfter);
};

testAddTodo();
testToggleTodo();
console.log("All tests passed");

Issue is, within the todoReducer function, following syntax is not working:

return {
        ...state,
        completed: !state.completed
      };

I am using Firefox version 44.0 and it shows me following error in console:

Invalid property id

Now I guess my current version of Firefox must support Spread operator. If anyway it does not, is there any way to add some standalone Polyfill to support this syntax?

Here is also the JSFiddle

Faisal Mq
  • 5,036
  • 4
  • 35
  • 39
  • For completeness: [`...` is not an operator!](https://stackoverflow.com/questions/37151966/what-is-spreadelement-in-ecmascript-documentation-is-it-the-same-as-spread-oper/37152508#37152508) – Felix Kling Feb 19 '18 at 21:58

3 Answers3

8

The object spread syntax is not supported in most browsers at the minute. It's proposed for addition in ES7 (aka ES2016). As far as I know there's no way to polyfill it, as it uses a new syntax rather than just being a function call.

You have two options in the meantime.

1) Use Object.assign to create an updated version of the object, like so:

Object.assign({}, state, {
  completed: !state.completed
});

Although this will also need to be polyfilled in most browsers - a good example one is available on MDN, or you can use a third party library's version, like the one in lodash.

2) Use transpiling tools like Babel, which allow you to write your code with newer syntax and then convert it to a version that works in all browsers.

Joe Clay
  • 33,401
  • 4
  • 85
  • 85
2

If anyone using Babel is still having trouble, this feature may not be available with Babel out of the box, you may need to add a plugin: http://babeljs.io/docs/plugins/transform-object-rest-spread/

then update .babelrc with

"plugins": ["transform-object-rest-spread"]

Erik Waters
  • 177
  • 1
  • 13
1

You can not polyfill syntax. You need to use something like babel to compile to an older version of JavaScript if you wish to execute in current browsers.

https://babeljs.io/

ekuusela
  • 5,034
  • 1
  • 25
  • 43
  • OK, so how can I use Babel along with my supplied JSFiddle in question? [UPDATE] I guess I have already added babel.min.js file as an external resource in my fiddle. But its still not working. – Faisal Mq Feb 10 '16 at 09:52
  • 1
    Babel is a tool you run on the command line/through a task runner. You won't be able to include it in a jsFiddle. – Joe Clay Feb 10 '16 at 10:09
  • 2
    @FaisalMq: you can set jsFiddle's language to Bable. – Felix Kling Feb 10 '16 at 14:24
  • @JoeClay: browser versions are also available. – Felix Kling Feb 10 '16 at 14:24
  • My bad, I didn't realize jsFiddle supported it as a syntax. And a browser version used to be available, but it's now been deprecated: https://babeljs.io/docs/usage/browser/. They do provide a link to a third-party implementation (`babel-standalone`) now, however. – Joe Clay Feb 10 '16 at 15:08
  • OK found what I was looking for, via @FelixKling's comment. On jsFiddle set Babel as Language from top right gear icon in javascript pane. – Faisal Mq Feb 11 '16 at 07:42
  • I believe this helps [babel object rest spread](http://babeljs.io/docs/plugins/transform-object-rest-spread/) – matt93 Jul 18 '16 at 14:10