做一个redux todo来学习并在切换待办事项上遇到麻烦。
当我触发onclick时,我在控制台中收到错误。
"道具类型失败:道具items
在ItemsList
标记为必需,但其值为undefined
。"
和
"无法读取属性'长度'未定义" on items.length
我安慰记录了这个动作,它似乎正在恢复状态。不确定我做错了什么。代码如下。
动作
export const addItem = content => {
return { type: ADD_ITEM, content };
};
export const toggleTodo = (id) => {
return {
type: TOGGLE_TODO,
id,
};
};
我的初始状态是:
import { ADD_ITEM, TOGGLE_TODO } from './constants';
let nextId = 4;
export const initialState = {
items: [
{ id: 1, content: 'Call mum', completed: false},
{ id: 2, content: 'Buy cat food', completed: true },
{ id: 3, content: 'Water the plants', completed: false },
],
};
const reducer = (state = initialState, action) => {
console.log("action", action.type);
switch (action.type) {
case ADD_ITEM:
const newItem = {
id: nextId++,
content: action.content,
completed: false
};
return {
...state,
items: [...state.items, newItem],
};
case TOGGLE_TODO:
return state.items.map(todo => {
console.log("state", state);
console.log("state.items", state.items);
console.log("todo",todo);
if (todo.id !== action.id) {
return state;
}
return {
...state,
completed: !todo.completed,
};
});
default:
return state;
}
};
export default reducer;
我的列表组件是
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Todo from "../ItemTodo/index"
import { toggleTodo } from "../../logic/actions";
import './styles.css';
export const ItemsList = ({ items, onTodoClick }) => {
return (
<div>
<ul className={'itemsList-ul'}>
{items.length < 1 && <p id={'items-missing'}>Add some tasks above.</p>}
{items.map(item =>
<Todo
key={item.id}
{...item}
onClick={() => onTodoClick(item.id)}
/>
)}
</ul>
</div>
);
};
ItemsList.propTypes = {
items: PropTypes.array.isRequired,
onTodoClick: PropTypes.func.isRequired,
};
const mapStateToProps = state => {
return { items: state.todos.items };
};
const mapDispatchToProps = dispatch => ({
onTodoClick: id => dispatch(toggleTodo(id))
});
export default connect(mapStateToProps, mapDispatchToProps)(ItemsList);
我的待办事项组件是
import React from 'react';
import PropTypes from 'prop-types';
const Todo = ({onClick, completed, content }) => (
<li
onClick={onClick}
style={{
textDecoration: completed ? 'line-through' : 'none',
}}
>
{content}
</li>
);
Todo.propTypes = {
onClick: PropTypes.func.isRequired,
completed: PropTypes.bool.isRequired,
content: PropTypes.string.isRequired,
};
export default Todo;
创建商店
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import configureStore from './redux/store';
import Header from './components/Header';
import ItemCreator from './components/ItemCreator';
import ItemsList from './components/ItemsList';
import './app.css';
const store = configureStore();
class App extends Component {
render() {
return (
<Provider store={store}>
<div className="app">
<Header />
<div>
<ItemCreator />
<ItemsList />
</div>
</div>
</Provider>
);
}
}
export default App;
import { createStore, applyMiddleware, compose } from 'redux';
import createReducer from './reducers';
const composeEnhancers =
(process.env.NODE_ENV !== 'production' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
compose;
const configureStore = (initialState = {}) => {
return createStore(
createReducer(),
initialState,
composeEnhancers(applyMiddleware())
);
};
export default configureStore;
import { combineReducers } from 'redux';
import reducer from '../logic/reducer';
export default function createReducer() {
return combineReducers({
todos: reducer,
});
}
答案 0 :(得分:0)
我还没有测试过,但我认为这部分不正确TOGGLE_TODO
:
return state.items.map(todo => {
console.log("state", state);
console.log("state.items", state.items);
console.log("todo",todo);
if (todo.id !== action.id) {
return state;
}
return {
...state,
completed: !todo.completed,
};
});
它应该是:
return {
...state,
items: state.items.map((todo) => {
if (todo.id === action.id) {
return { ...todo, completed: !todo.completed };
}
return todo;
})
};