组件内的 React 状态更改(通过 mapDispatchToProps)给出错误
Changes to React state within the Component(via mapDispatchToProps) gives error
我从这里开始关注 redux 的 Todo 示例 https://github.com/reactjs/redux/tree/master/examples/todos
我做了一些小改动。我正在接受我的待办事项中的更多字段。
{text, time, by}
并在 table 中显示这些详细信息。
我想按时间订购这个table。我 不想 想要遵循此用例的 redux 模式。为什么你问!
对于像订购这样简单的事情,我不想在状态中添加它。我想在 React state itself
内维护这些功能。由于 VisibleTodoList 是一个智能组件,其状态具有待办事项,因此我希望能够按照我喜欢的方式对其重新排序。
我的VisibleTodoList.js
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'SHOW_ALL':
return todos
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed)
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed)
default:
throw new Error('Unknown filter: ' + filter)
}
}
const orderTime = (todos) => {
console.log('inside order time!'); //Displays this. comes inside here.
return todos.filter(t => t.time > 20) //This gives me error!!
}
const mapStateToProps = (state) => ({
todos: getVisibleTodos(state.todos, state.visibilityFilter), // I do not want to add more things to the state. Want to keep it simple.
})
const mapDispatchToProps = ({
onTodoClick: toggleTodo,
onTimeClick: orderTime //My function defined above to returned filtered todos.
})
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
export default VisibleTodoList
TodoList.js
看起来像这样
const TodoList = ({ todos, persons, onTodoClick, completed, onTimeClick}) => (
<div>
<table>
<tbody>
<tr>
<th>Task Name</th>
<th
onClick={() => onTimeClick(todos)}
style={{
textDecoration: completed ? 'line-through' : 'none'
}}>Time</th>
<th>By person</th>
</tr>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
/>
)}
</tbody>
</table>
</div>
)
我的todo.js看起来几乎一样
const Todo = ({ onClick, completed, text, time, by }) => (
<tr key={text}>
<td style={{
textDecoration: completed ? 'line-through' : 'none'}}>{text}</td>
<td>{time}</td>
<td>{by}</td>
</tr>
)
当我点击“时间”列时,我总是收到这个错误
Actions must be plain objects. Use custom middleware for async actions.
我做错了什么?
另外我应该遵循什么模式来实现这一目标?在不偏离 redux 模式的情况下。我必须使用 setState
为了提供更多上下文,我希望有一个本地 UI 状态,而不是在 redux 存储中。就像这里解释的那样
更新 1:我确实理解因为 orderTime
没有调度它抱怨的对象。但是我更广泛的问题是我是否必须实现相同的功能。我该怎么做?
如果我理解正确,我将不得不使用 setState
来执行此操作。
这是迄今为止我能想到的最佳解决方案!
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'WEIGHT_SORT':
return _.sortBy(todos, [function(o) { return o.time; }]);
default:
throw new Error('Unknown filter: ' + filter)
}
}
class TodoList extends React.Component {
state = { filter: 'SHOW_ALL' }
handleShow = filter => {
this.setState({ filter: 'WEIGHT_SORT' })
}
render(){
const filteredTodos = getVisibleTodos(todos, this.state.filter)
return (
<div>
<table>
<tbody>
<tr>
<th>Task Name</th>
<th
onClick={() => this.handleShow('SHOW_COMPLETED')}>Time</th>
<th>By person</th>
</tr>
{filteredTodos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => this.props.onTodoClick(todo.id)}
/>
)}
</tbody>
</table>
</div>
)
}
}
这是 UI 调整(排序、排序和其他操作),我们将其保持在 React 本地状态。这会导致更清晰的代码,因为我们的 redux state
是干净的并且不会存储所有这些信息。
打开 suggestions/comments 和更好的答案!
我从这里开始关注 redux 的 Todo 示例 https://github.com/reactjs/redux/tree/master/examples/todos
我做了一些小改动。我正在接受我的待办事项中的更多字段。
{text, time, by}
并在 table 中显示这些详细信息。
我想按时间订购这个table。我 不想 想要遵循此用例的 redux 模式。为什么你问!
对于像订购这样简单的事情,我不想在状态中添加它。我想在 React state itself
内维护这些功能。由于 VisibleTodoList 是一个智能组件,其状态具有待办事项,因此我希望能够按照我喜欢的方式对其重新排序。
我的VisibleTodoList.js
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'SHOW_ALL':
return todos
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed)
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed)
default:
throw new Error('Unknown filter: ' + filter)
}
}
const orderTime = (todos) => {
console.log('inside order time!'); //Displays this. comes inside here.
return todos.filter(t => t.time > 20) //This gives me error!!
}
const mapStateToProps = (state) => ({
todos: getVisibleTodos(state.todos, state.visibilityFilter), // I do not want to add more things to the state. Want to keep it simple.
})
const mapDispatchToProps = ({
onTodoClick: toggleTodo,
onTimeClick: orderTime //My function defined above to returned filtered todos.
})
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
export default VisibleTodoList
TodoList.js
看起来像这样
const TodoList = ({ todos, persons, onTodoClick, completed, onTimeClick}) => (
<div>
<table>
<tbody>
<tr>
<th>Task Name</th>
<th
onClick={() => onTimeClick(todos)}
style={{
textDecoration: completed ? 'line-through' : 'none'
}}>Time</th>
<th>By person</th>
</tr>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
/>
)}
</tbody>
</table>
</div>
)
我的todo.js看起来几乎一样
const Todo = ({ onClick, completed, text, time, by }) => (
<tr key={text}>
<td style={{
textDecoration: completed ? 'line-through' : 'none'}}>{text}</td>
<td>{time}</td>
<td>{by}</td>
</tr>
)
当我点击“时间”列时,我总是收到这个错误
Actions must be plain objects. Use custom middleware for async actions.
我做错了什么?
另外我应该遵循什么模式来实现这一目标?在不偏离 redux 模式的情况下。我必须使用 setState
为了提供更多上下文,我希望有一个本地 UI 状态,而不是在 redux 存储中。就像这里解释的那样
更新 1:我确实理解因为 orderTime
没有调度它抱怨的对象。但是我更广泛的问题是我是否必须实现相同的功能。我该怎么做?
如果我理解正确,我将不得不使用 setState
来执行此操作。
这是迄今为止我能想到的最佳解决方案!
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'WEIGHT_SORT':
return _.sortBy(todos, [function(o) { return o.time; }]);
default:
throw new Error('Unknown filter: ' + filter)
}
}
class TodoList extends React.Component {
state = { filter: 'SHOW_ALL' }
handleShow = filter => {
this.setState({ filter: 'WEIGHT_SORT' })
}
render(){
const filteredTodos = getVisibleTodos(todos, this.state.filter)
return (
<div>
<table>
<tbody>
<tr>
<th>Task Name</th>
<th
onClick={() => this.handleShow('SHOW_COMPLETED')}>Time</th>
<th>By person</th>
</tr>
{filteredTodos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => this.props.onTodoClick(todo.id)}
/>
)}
</tbody>
</table>
</div>
)
}
}
这是 UI 调整(排序、排序和其他操作),我们将其保持在 React 本地状态。这会导致更清晰的代码,因为我们的 redux state
是干净的并且不会存储所有这些信息。
打开 suggestions/comments 和更好的答案!