反应独特的“关键”错误

2024-05-30

我正在浏览 React 中的待办事项列表教程,并遇到以下错误,我花了相当长的时间,只是找不到错误..这是错误和组件的代码,这就是代码对于课程存储库(此提交中出现问题):

https://github.com/andrewjmead/react-course-todo-app/commit/0521f151705f78cb9f8d69262eb093f1431cb9ca https://github.com/andrewjmead/react-course-todo-app/commit/0521f151705f78cb9f8d69262eb093f1431cb9ca

非常感谢任何帮助。

警告:数组或迭代器中的每个子项都应该有一个唯一的“key”属性。检查渲染方法TodoList。请参阅 fb.me/react-warning-keys 了解更多信息。

对于 TOGGLE_TODO 情况下的展开运算符,终端中也会出现错误

return {
...todo, // here
completed: nextCompleted,
completedAt: nextCompleted ? moment().unix() : undefined
};

var React = require('react');
var { connect } = require('react-redux');
import Todo from 'Todo';
var TodoAPI = require('TodoAPI');

export var TodoList = React.createClass ({
    render: function() {
        var { todos, showCompleted, searchText } = this.props;
        var renderTodos = () => {
            if(todos.length === 0) {
                return (
                    <p className="container__message">No tasks</p>
                );
            }
            return TodoAPI.filterTodos(todos, showCompleted, searchText).map((todo) => {
                return (
                    //add unique key prop to keep track of individual components
                    <Todo key={todo.id} {...todo} />
                );
            });
        };
        return (
            <div>
                {renderTodos()}
            </div>
        );  
    }
});

export default connect(
    (state) => {
        return state;
    }
)(TodoList);

减速机:

var uuid = require('uuid');
var moment = require('moment');

export var searchTextReducer = (state = '', action) => {
    switch (action.type) {
        case 'SET_SEARCH_TEXT':
            return action.searchText;
        default: 
            return state;
    };
};

export var showCompletedReducer = (state = false, action) => {
    switch (action.type) {
        case 'TOGGLE_SHOW_COMPLETED':
            return !state;
        default: 
            return state;
    };    
};

export var todosReducer = (state = [], action) => {
    switch(action.type) {
        case 'ADD_TODO':
            return [
                ...state,
                {
                    text: action.text,
                    id: uuid(),
                    completed: false,
                    createdAt: moment().unix(),
                    completedAt: undefined                   
                }
            ];
        case 'TOGGLE_TODO':
            return state.map((todo) => {
                if(todo.id === action.id) {
                    var nextCompleted = !todo.completed;

                    return {
                        ...todo,
                        completed: nextCompleted,
                        completedAt: nextCompleted ? moment().unix() : undefined
                    };
                } else {
                    return todo;
                }
            });
        case 'ADD_TODOS':
            return [
                ...state,
                ...action.todos
            ];
        default: 
            return state;
    }
};


Webpack:

var webpack = require('webpack');

module.exports = {
  entry: [
    'script!jquery/dist/jquery.min.js',
    'script!foundation-sites/dist/js/foundation.min.js',
    './app/app.jsx'
  ],
  externals: {
      jquery: 'jQuery'
  },
  plugins: [
      new webpack.ProvidePlugin({
          '$': 'jquery',
          'jQuery': 'jquery'
      })
  ],
  output: {
    path: __dirname,
    filename: './public/bundle.js'
  },
  resolve: {
    root: __dirname,
    modulesDirectories: [
        'node_modules',
        './app/components',
        './app/api'
    ],
    alias: {
        applicationStyles: 'app/styles/app.scss',
        actions: 'app/actions/actions.jsx',
        reducers: 'app/reducers/reducers.jsx',
        configureStore: 'app/store/configureStore.jsx'
    },
    extensions: ['', '.js', '.jsx']
  },
  module: {
    loaders: [
      {
        loader: 'babel-loader',
        query: {
          presets: ['react', 'es2015']
        },
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/
      }
    ]
  },
  devtool: 'cheap-module-eval-source-map'
};

在 React 中,当你渲染多个相同的组件(在你的例子中是待办事项)时,你需要为每个组件添加一个唯一的键,这是因为 React 需要知道它们将如何在虚拟 dom 中被处理。

您可以采取多种措施来解决此问题:

  1. 在 for 循环中,创建一个索引变量,并在每次循环结束时将其加 1,然后将其设置为每个渲染组件的键。

  2. 如果您要从 api 获取待办事项,请为每个待办事项设置一个 id 并将其用作组件密钥。

  3. 使用随机数生成器为每个待办事项设置唯一的密钥。

最好的方法是#2和#3,我发现在你的情况下,你正在尝试执行#2(通过todo id设置密钥),但我认为它是未定义的,请检查它。

另一种解决方案是使用uuid https://en.wikipedia.org/wiki/Universally_unique_identifier在每个渲染的组件/待办事项上。

为此,您可以安装节点 uuid https://github.com/kelektiv/node-uuid.

Run: npm i --save node-uuid

然后在您的文件中进行导入:import uuid from 'node-uuid' or const uuid = require('node-uuid')

现在将您的代码更改为如下所示:

return TodoAPI.filterTodos(todos, showCompleted, searchText).map((todo) => {
  return (
    //add unique key prop to keep track of individual components
    <Todo key={uuid()} {...todo} />
  );
});

然后你就可以开始了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

反应独特的“关键”错误 的相关文章

随机推荐

  • 对无符号 8 位整数进行左移操作 [重复]

    这个问题在这里已经有答案了 我试图理解 C C 中的移位运算符 但它们给我带来了困难 我有一个无符号 8 位整数 初始化为一个值 例如 1 uint8 t x 1 根据我的理解 它在内存中的表示方式如下 0 0 0 0 0 0 0 1 现在
  • 如何获取 Spotify API 的访问令牌?

    我已经研究 Spotify api 和示例源代码几天了 但我仍然不知道如何获取访问令牌来访问用户的播放列表数据 我已经到达了拉起登录窗口 用户登录 然后收到授权码的地步 此时 我尝试做这样的事情 window open https acco
  • 免费和付费版本 Android 应用程序的最佳方法?

    我开发了一个 Android 应用程序 我希望它可以作为免费版本和付费版本提供 最好的方法是什么 我可以想到三种解决方案 将项目分成两个分支并维护它们 创建一个库项目并有两个附加项目 一个 免费 版本和一个 付费 版本 使用应用内结算 问
  • 如何去除html源代码中的空格

    我正在使用 django 和 python 在模板文件中 我有一个下拉列表 如下所示 有用 唯一的问题是源 html 代码之间有很多空白 有什么办法可以去除空白吗 谢谢 for lang ele in video languages all
  • Keycloak - 代理后面的 URL 重置密码电子邮件

    我们正在使用钥匙斗篷 2 0 0 Final安装在后面Nginx 代理在 RedHat 环境上 我们目前面临的问题是重设密码使用内部服务器主机而不是操作 URL 中的外部服务器发送电子邮件的功能 因为我们位于代理后面 我通过电子邮件收到此信
  • JavaScript/jQuery - “$ 未定义 - $function()”错误

    我正在尝试运行 JavaScript jQuery 函数并且Firebug http en wikipedia org wiki Firebug 28software 29得到错误 is not defined function JavaS
  • Python SQLite3 SQL注入漏洞代码

    我知道下面的代码片段由于 format 的原因很容易受到 SQL 注入的攻击 但我不知道为什么 有谁明白为什么这段代码容易受到攻击以及我从哪里开始修复它 我知道这些代码片段使输入字段保持打开状态 以便通过 SQL 注入执行其他恶意命令 但不
  • Mysql为简单频繁查询创建排序索引性能

    我正在处理一个包含大约 400 万条消息条目的 mysql 表 并尝试根据时间戳选择最新的 50 条消息 另一个要求是返回的消息不以固定前缀开头 问题是单个查询大约占用 25 的 cpu 并且最多需要 1 5 秒 该查询经常由多个客户端执行
  • 如何在socket.io Nodejs服务器上列出房间

    在问题取得进展后如何创建socket io多播组 https stackoverflow com questions 6616922 how to create socket io multicast groups 6624604 6624
  • 是否有 Ubuntu 10.04 存储库可以下载最新版本的 Eclipse?

    我还没有找到一个可以安装 Eclipse 4 2 Juno 的软件 默认的 Ubuntu 存储库 我使用的是 Ubuntu 10 04 建议我使用古老的 Galileo 版本 我在 Launchpad 上找到了 Eclipse 的页面 该页
  • play20 ebean 生成的 sql 在 postgresql 上抛出语法错误

    我正在尝试使用 postgresql 来启动我的 play20 应用程序 以便我可以使用并稍后部署到 Heroku 我跟着这个answer https stackoverflow com questions 12195568 errors
  • REASSIGN OWNED BY 为 1 个指定数据库

    我想使用以下命令更改一个特定数据库中所有表的所有者 REASSIGN OWNED BY postgres TO myuser 但它显示 ERROR cannot reassign ownership of objects owned by
  • 如何让android BottomAppBar圆角化

    我正在使用BottomAppBar来自谷歌这样的
  • 如何使用 asp.net 5 项目运行 nunit 测试,尤其是使用 ReSharper?

    我正在开发一个针对 dnx451 的 asp net 5 应用程序 asp net 5 项目依赖于一些为 nunit 2 x 编写的带有单元测试的库 所以对我来说合理的选择是使用 nunit 来测试 asp net 5 项目 当我在 ReS
  • Spring Boot 多部分文件始终为 null

    我正在使用 Spring Boot version 1 4 0 RC1 和 Spring Boot Stormpath 1 0 2 我正在尝试使用分段文件上传 但控制器中的 MultipartFile 始终为空 当我使用 RequestPa
  • Python MySQLdb:connection.close() VS。光标.close()

    如果我使用MySQLdb通过Python连接到MySQL Server 我创建一个connection and a cursor像这样 connection MySQLdb connect cursor connection cursor
  • 在 JavaFX 中更改 ListView 字体大小

    我想知道如何更改 JavaFx 中的列表视图项目文本字体大小 每行文本的大小会有所不同 我尝试使用细胞因子属性 但我不知道如何使用它 有人可以帮我吗 类似的问题在这里 如何更改JavaFX中ListView的字体大小 https stack
  • 为什么java(>=7版本)不支持运行没有main方法的程序? [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 class WithoutMain static System out println Without main class Sy
  • 如何在具有多种字体大小的 TextView 中调整行高?

    我有一个包含 Spannable 字符串的 TextView 该字符串包含一堆文本 其中第一个单词的字体大小是字符串其余部分的两倍 问题在于 由于第一个字的大小增加 第一行和第二行之间的行间距比后续行之间的行间距大得多 http img s
  • 反应独特的“关键”错误

    我正在浏览 React 中的待办事项列表教程 并遇到以下错误 我花了相当长的时间 只是找不到错误 这是错误和组件的代码 这就是代码对于课程存储库 此提交中出现问题 https github com andrewjmead react cou