我正在尝试使用npm运行egghead.io中的storeApp。
当我运行该应用程序时,它说我出错了。
未捕获的TypeError:无法读取未定义的属性'combineReducers'
webpack.config.js
module.exports = {
entry: './main.js',
output: {
path: './',
filename: 'index.js'
},
devServer: {
inline: true,
port: 2220
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}
]
}
}
package.json
{
"name": "redux",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"babel": "^6.5.2",
"babel-core": "^6.7.6",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"react": "^0.14.8",
"react-redux": "^4.4.2",
"webpack": "^1.12.15",
"webpack-dev-server": "^1.14.1"
},
"devDependencies": {
"redux-devtools": "^3.2.0"
},
"scripts": {
"start": "webpack-dev-server"
},
"author": "",
"license": "ISC"
}
/*
* We will be explaining the code below
* in the following lessons. For now,
* feel free to click around and notice
* how the current state tree is logged
* to the console on every change.
*/
import React from 'react';
import ReactDOM from 'react-dom';
import Redux from 'redux';
import { createStore, combineReducers } from 'redux';
const ADD_TODO = 'ADD_TODO';
const TOGGLE_TODO = 'TOGGLE_TODO';
const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';
const Filters = {
SHOW_ALL: 'SHOW_ALL',
SHOW_COMPLETED: 'SHOW_COMPLETED',
SHOW_ACTIVE: 'SHOW_ACTIVE'
};
/*
* Components
*/
class AddTodo extends React.Component {
render() {
return (
<div>
<input type='text' ref='input' />
<button onClick={(e) => this.handleClick(e)}>
Add
</button>
</div>
);
}
handleClick(e) {
const node = this.refs.input;
const text = node.value.trim();
this.props.onAddClick(text);
node.value = '';
}
}
const FilterLink = ({ isActive, name, onClick }) => {
if (isActive) {
return <span>{name}</span>;
}
return (
<a href='#' onClick={e => { e.preventDefault(); onClick(); }}>
{name}
</a>
);
};
const Footer = ({ filter, onFilterChange }) => (
<p>
Show:
{' '}
<FilterLink
name='All'
isActive={filter === Filters.SHOW_ALL}
onClick={() => onFilterChange(Filters.SHOW_ALL)} />
{', '}
<FilterLink
name='Completed'
isActive={filter === Filters.SHOW_COMPLETED}
onClick={() => onFilterChange(Filters.SHOW_COMPLETED)} />
{', '}
<FilterLink
name='Active'
isActive={filter === Filters.SHOW_ACTIVE}
onClick={() => onFilterChange(Filters.SHOW_ACTIVE)} />
</p>
);
const Todo = ({ onClick, completed, text }) => (
<li
onClick={onClick}
style={{
textDecoration: completed ? 'line-through' : 'none',
cursor: 'pointer'
}}>
{text}
</li>
);
const TodoList = ({ todos, onTodoClick }) => (
<ul>
{todos.map(todo =>
<Todo {...todo}
key={todo.id}
onClick={() => onTodoClick(todo.id)} />
)}
</ul>
);
let nextTodoId = 0;
const TodoApp = ({ dispatch, todos, visibilityFilter }) => {
let visibleTodos = todos;
switch (visibilityFilter) {
case Filters.SHOW_COMPLETED:
visibleTodos = todos.filter(todo => todo.completed);
break;
case Filters.SHOW_ACTIVE:
visibleTodos = todos.filter(todo => !todo.completed);
break;
}
return (
<div>
<AddTodo
onAddClick={text =>
dispatch({ type: ADD_TODO, text, id: nextTodoId++ })
} />
<TodoList
todos={visibleTodos}
onTodoClick={id =>
dispatch({ type: TOGGLE_TODO, id })
} />
<Footer
filter={visibilityFilter}
onFilterChange={filter =>
dispatch({ type: SET_VISIBILITY_FILTER, filter })
} />
</div>
);
};
/*
* Reducers
*/
const visibilityFilter = (state = Filters.SHOW_ALL, action) => {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return action.filter;
default:
return state;
}
}
const todos = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [...state, {
text: action.text,
id: action.id,
completed: false
}];
case TOGGLE_TODO:
return state.map(todo =>
todo.id === action.id ?
Object.assign({}, todo, { completed: !todo.completed }) :
todo
);
default:
return state;
}
}
const todoApp = Redux.combineReducers({
visibilityFilter,
todos
});
/*
* Go!
*/
const store = Redux.createStore(todoApp);
const dispatch = (action) => {
store.dispatch(action);
console.log('----------------');
console.log('current state:');
console.log(store.getState());
}
const render = () => {
ReactDOM.render(
<TodoApp
{...store.getState()}
dispatch={dispatch}
/>,
document.getElementById('root')
);
}
render();
store.subscribe(render);
console.log('current state:');
console.log(store.getState());
// noprotect
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script src="index.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="root">
</div>
</body>
最佳答案
我认为您也缺少redux软件包。添加到您的package.json
npm install --save-dev redux
注意:您的应用程序名称也为redux,因此npm在安装时会向您抛出错误。
提示:另外,我建议您使用--save-dev选项安装所有依赖项。这是为了在构建生产版本时优化捆绑包的大小,因此webpack仅包含必要的组件,而不包括整个库。