这是我的减速器:
export interface RootState {
todos: ToDo[];
}
const initialState = {
todos: []
};
export const todo = (
state: RootState = initialState,
action: Action
): RootState => {
switch (action.type) {
case TODO_ADD:
return {
todos: [...state.todos, action.payload.todo]
};
case TODO_TOGGLE_COMPLETE:
let todoArr = [...state.todos];
todoArr.forEach((todo: ToDo, index: number) => {
if (todo.id === action.payload.id) {
todoArr[index].isComplete = !todo.isComplete;
}
});
return {
todos: todoArr
};
default:
return state;
}
};
动作:
export const TODO_ADD = "TODO_ADD";
export const TODO_TOGGLE_COMPLETE = "TODO_TOGGLE_COMPLETE";
export interface Action {
type: string;
payload: any;
}
export interface ToDo {
id: string;
todo: string;
isComplete: boolean;
}
const add = (todo: ToDo): Action => ({
type: TODO_ADD,
payload: { todo }
});
export const toggleComplete = (id: string): Action => ({
type: TODO_TOGGLE_COMPLETE,
payload: { id }
});
export const addToDo = (todo: ToDo) => (dispatch: any) => {
dispatch(add(todo));
};
和我要调用的组件切换完成:
import * as React from "react";
import { Button, Row, Col } from "antd";
import styled from "styled-components";
import { ToDo, toggleComplete } from "src/actions/todo";
import { connect } from "react-redux";
const mapDispatchToProps = (dispatch: any) => ({
toggleComplete: (id: string) => dispatch(toggleComplete(id))
});
type MapDispatchToProps = ReturnType<typeof mapDispatchToProps>;
type Props = MapDispatchToProps & {
todo: ToDo;
};
class TodoItem extends React.Component<Props> {
render() {
const { todo } = this.props;
return (
<Container>
<Col span={20}>
<h3>{todo.todo}</h3>
</Col>
<Col span={4}>
<Button
type="primary"
onClick={() => this.props.toggleComplete(this.props.todo.id)}
>
{todo.isComplete ? "Completed" : "Complete"}
</Button>
</Col>
</Container>
);
}
}
const Container = styled(Row)`
width: 100%;
`;
export default connect<undefined, MapDispatchToProps>(
undefined,
mapDispatchToProps
)(TodoItem);
todo
从组件列表中获取
import * as React from "react";
import { List } from "antd";
import styled from "styled-components";
import TodoItem from "./TodoItem";
import { connect } from "react-redux";
import { RootState } from "src/reducers/todo";
import { ToDo } from "src/actions/todo";
const mapStateToProps = (state: RootState) => ({
todos: state.todos
});
type StateProps = ReturnType<typeof mapStateToProps>;
class TodoList extends React.Component<StateProps> {
render() {
const { todos } = this.props;
return (
<Container>
<List
header={
<div>
<h2>Todo List</h2>
<h4>
There are {todos.length} {todos.length === 1 ? "todo" : "todos"}
</h4>
</div>
}
bordered
dataSource={todos}
renderItem={(todo: ToDo) => (
<List.Item>
<TodoItem todo={todo} />
</List.Item>
)}
/>
</Container>
);
}
}
const Container = styled.div`
width: 100%;
margin-top: 30px;
`;
export default connect(mapStateToProps)(TodoList);
我已经实现了订阅:
store.subscribe(() => console.log(store.getState()));
并查看状态已更改,但组件未重新呈现。
答案 0 :(得分:4)
问题在于您如何简化化简器中的状态。从此更改化简文件中的第24行
todoArr[index].isComplete = !todo.isComplete;
对此
todoArr[index] = {...todo, isComplete: !todo.isComplete};
基本上,您试图做的是直接更改状态对象,而不是创建新的对象签名。
您将要遇到的另一个问题是当前您正在创建具有相同ID的新待办事项。因此,当您完成一项时,所有项目都标记为已完成。取而代之的是,您可以仅使用当前时间戳作为唯一ID。
更改此
const todo: ToDo = {
id: "1",
todo: value,
isComplete: false
};
this.props.addToDo(todo);
对此
const todo: ToDo = {
id: `${new Date().valueOf()}`,
todo: value,
isComplete: false
};
this.props.addToDo(todo);