定义密钥后,为什么在ASp.NET React项目中出现“唯一的“密钥”道具”错误?

时间:2018-10-08 13:38:12

标签: asp.net reactjs

我正在一个新的react项目中,我试图找到自己的进度,并开始研究获取数据的简单方法。我试图使用一个简单的数据列表将其输出到列表中。当我尝试运行页面时,出现以下错误:

  

警告:数组或迭代器中的每个子代均应具有唯一的“键”   支柱。检查FetchData的渲染方法。

我开始四处寻找答案,并在此处找到许多文章,说您需要添加键值。我以为我已经做到了,但是没有用。在这种情况下,关键值是汽车的Id,但我仍然收到错误消息。

我查看了React文档,得到了相同的答案,并添加了一个唯一密钥。那么,我的ID无效吗?还是还有其他情况?

这是我的代码,从控制器开始。

SampleDataController.cs

namespace Lothric.UI.Controllers
{
    [Route("api/[controller]")]
    public class SampleDataController : Controller
    {    
        [HttpGet("[action]")]
        public IEnumerable<Car> Cars()
        {
            var data = new List<Car>
            {
                new Car {
                    Id = 1,
                    Make = "Nissan",
                },
                new Car {
                    Id = 2,
                    Make = "Audi"
                }
            };
            return data;
        }

        public class Car
        {
            [Key]
            public int Id { get; set; }
            public string Make { get; set; }
        }
    }
}

FetchData.tsx

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import 'isomorphic-fetch';
import { Key } from 'react';

interface FetchDataExampleState {
    cars: Cars[];
    loading: boolean;
}

export class FetchData extends React.Component<RouteComponentProps<{}>, FetchDataExampleState> {
    constructor() {
        super();
        this.state = { cars: [], loading: true };

        fetch('api/SampleData/Cars')
            .then(response => response.json() as Promise<Cars[]>)
            .then(data => {
                this.setState({ cars: data, loading: false });
            });
    }

    public render() {
        let contents = this.state.loading
            ? <p><em>Loading...</em></p>
            : FetchData.renderCarsTable(this.state.cars);

        return <div>
            <h1>Cars</h1>
            <p>This component demonstrates fetching data from the server.</p>
            { contents }
        </div>;
    }

    private static renderCarsTable(cars: Cars[]) {
        return <ul>
            {cars.map((cars) =>
                <li key={cars.Id}>{cars.Make}</li>
            )}
            </ul>;
    }
}

interface Cars {
    Id: number;
    Make: string;
}

我认为这可能很简单,但是我无法解决它,因此需要一些指导:)谢谢

2 个答案:

答案 0 :(得分:0)

使用Reconciliation方法来比较元素并创建虚拟DOM。如果要使用map(循环)方法创建任何组件,请确保在给定的循环中每个组件都有唯一的键。

private static renderCarsTable(cars: Cars[]) {
    return <ul>
        {carss.map((cars) =>
            <li key={cars.Id}>{cars.Make}</li>
        )}
        </ul>;
}

在这种情况下,您有一个包含ID的汽车对象数组,但不能确保2个项目中的任何一个都不具有相同的ID。在这种情况下,我建议也使用map函数的索引

private static renderCarsTable(cars: Cars[]) {
    return <ul>
        {carss.map((cars, index) =>
            <li key={`${cars.Id}-${index}`}>{cars.Make}</li>
        )}
        </ul>;
}

现在map函数中的每个元素都会有一个唯一的键

答案 1 :(得分:-1)

谢谢大家的答复。如果您在控制台中查看从Cars返回的原始数据,这似乎是一个简单的错误,您可以看到所有名称都是小写的。因此IdidMakemake。我在界面中然后在渲染组件中更改了这些项目,效果很好。

private static renderCarsTable(cars: Cars[]) {
        return <ul>
            {cars.map((cars) =>
                <li key={cars.id}>{cars.make}</li>
            )}
            </ul>;
    }
}

interface Cars {
    id: number;
    make: string;
}

您无需在实际模型中仅更改要尝试呈现的内容即可对其进行更改。因此,仅重申一下,该渲染器原本期望idmake,但我正在定义IdMake这是行不通的。