我正在尝试使用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仅包含必要的组件,而不包括整个库。

10-06 10:58