Spread Operator не работает для примера на основе Redux/ES6
Я пытаюсь понять онлайн-учебники Redux, опубликованные Дэном Абрамовым. В настоящее время я нахожусь на следующем образце:
Вот мой практический код, следующий за приведенным выше примером:
// 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");
Проблема в функции todoReducer, следующий синтаксис не работает:
return {
...state,
completed: !state.completed
};
Я использую Firefox версии 44.0, и он показывает мне следующую ошибку в консоли:
Invalid property id
Теперь я думаю, что моя текущая версия Firefox должна поддерживать оператор Spread. Если в любом случае это не так, есть ли способ добавить какой-нибудь автономный Polyfill для поддержки этого синтаксиса?
Здесь также JSFiddle
3 ответа
Синтаксис распространения объекта в настоящее время не поддерживается большинством браузеров. Предлагается для добавления в ES7 (он же ES2016). Насколько я знаю, нет способа его заполнить, так как он использует новый синтаксис, а не просто вызов функции.
Тем временем у вас есть два варианта.
1) Использование Object.assign
создать обновленную версию объекта, вот так:
Object.assign({}, state, {
completed: !state.completed
});
Хотя в большинстве браузеров это также необходимо будет заполнить - хороший пример доступен в MDN, или вы можете использовать версию сторонней библиотеки, например, в lodash.
2) Используйте инструменты транспонирования, такие как Babel, которые позволяют писать код с более новым синтаксисом, а затем преобразовывать его в версию, которая работает во всех браузерах.
Если у кого-то, использующего Babel, все еще возникают проблемы, эта функция может быть недоступна с Babel "из коробки", вам может потребоваться добавить плагин: http://babeljs.io/docs/plugins/transform-object-rest-spread/
затем обновите.babelrc
"plugins": ["transform-object-rest-spread"]
Вы не можете polyfill синтаксис. Вам нужно использовать что-то вроде babel для компиляции в более старую версию JavaScript, если вы хотите выполнить в текущих браузерах.