失败的道具类型:道具todos [0] .id在TodoList中被标记为必需,但其值未定义

时间:2017-01-21 22:08:17

标签: reactjs redux react-redux

我正在尝试使用针对用户界面做出反应的redux basic usage tutorial

当我点击标有"添加Todo"

的按钮时,我在控制台日志中收到此警告(红色但可能是错误?)
  

warning.js:36警告:道具类型失败:道具todos[0].id是   标记为TodoList中的必填项,但其值为undefined。       在TodoList中(由Connect(TodoList)创建)       在Connect(TodoList)(在App.js:9)       在div(在App.js:7)       在App中(在index.js:12)       在提供者(在index.js:11)

所以添加的待办事项没有id字段 - 我需要弄清楚如何添加id。

actions.js

中的

/*
 * action creators
 */

export function addTodo(text) {
  return { type: ADD_TODO, text }
}

动作/ index.js

let nextTodoId = 0
export const addTodo = (text) => {
  return {
    type: 'ADD_TODO',
    id: nextTodoId++,
    text
  }
}

export const setVisibilityFilter = (filter) => {
  return {
    type: 'SET_VISIBILITY_FILTER',
    filter
  }
}

export const toggleTodo = (id) => {
  return {
    type: 'TOGGLE_TODO',
    id
  }
}

容器/ AddTodo.js

import React from 'react'
import { connect } from 'react-redux'
import { addTodo } from '../actions'

let AddTodo = ({ dispatch }) => {
  let input

  return (
    <div>
      <form onSubmit={e => {
        e.preventDefault()
        if (!input.value.trim()) {
          return
        }
        dispatch(addTodo(input.value))
        input.value = ''
      }}>
        <input ref={node => {
          input = node
        }} />
        <button type="submit">
          Add Todo
        </button>
      </form>
    </div>
  )
}
AddTodo = connect()(AddTodo)

export default AddTodo

看起来actions/index.js确实添加了待办事项id

很难调试,因为某些原因,chrome dev工具源缺少我的应用的actions和reducers文件夹:

enter image description here

enter image description here

如何让todos [0]拥有唯一ID?

请注意,当我在此处添加id: 1时,它会添加ID但不是唯一的:

function todos(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [
        ...state,
        {
          text: action.text,
          completed: false,
          id: 1
        }
      ]
    case TOGGLE_TODO:
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: !todo.completed
          })
        }
        return todo
      })
    default:
      return state
  }
}

也许:

/*
 * action creators
 */

export function addTodo(text) {
  return { type: ADD_TODO, text }
}

需要添加id吗?

2 个答案:

答案 0 :(得分:6)

我简要地查看了您的代码,我相信您没有得到id,因为您没有导入您认为自己的动作创建函数。

containers / AddTodo.js

import { addTodo } from '../actions'

在您的项目中,您有

./src/actions.js
./src/actions/index.js

当您导入或需要任何内容​​时(不使用上述'../actions'之类的文件扩展名),JS解释器将查看是否存在名为 actions.js 的文件 src 文件夹。如果没有,则会看到是否有操作文件夹,其中包含 index.js 文件。

既然你有这两个,你的AddTodo组件是使用 ./ src / actions.js 中的动作创建者导入的,它没有你原先猜到的id属性。

删除该文件,它应该按预期工作。

答案 1 :(得分:0)

您必须在操作文件中添加一个'id'变量,然后在每次调用操作创建者时增加该值。

动作创建者:

let nextTodoId = 0;

export const addTodo = text => ({
  type: 'ADD_TODO',
  id: nextTodoId++,
  text
});

减速器:

const todos = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          id: action.id, // unique id
          text: action.text,
          completed: false
        }
      ]
    case 'TOGGLE_TODO':
      return state.map(todo =>
        todo.id === action.id ? { ...todo, completed: !todo.completed } : todo
      )
    default:
      return state
  }
}