首页 > 解决方案 > 如何在 JSX 中获取数据并在页面上加载

问题描述

我正在尝试将 ASP.NET 核心与 React 和 JSX 一起使用。到目前为止,我能够获取数据,但是当我运行 FetchCustomer.tsx 时,它是空的。

这是控制器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ICTask1.Models;

namespace ICTask1.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CustomersController : ControllerBase
    {
        private readonly DBContext _context;

        public CustomersController(DBContext context)
        {
            _context = context;
        }

        // GET: api/Customers
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Customer>>> GetCustomer()
        {
            return await _context.Customer.ToListAsync();
        }

        // GET: api/Customers/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Customer>> GetCustomer(int id)
        {
            var customer = await _context.Customer.FindAsync(id);

            if (customer == null)
            {
                return NotFound();
            }
            return customer;
        }

        // PUT: api/Customers/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.
        [HttpPut("{id}")]
        public async Task<IActionResult> PutCustomer(int id, Customer customer)
        {
            if (id != customer.ID)
            {
                return BadRequest();
            }

            _context.Entry(customer).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!CustomerExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        // POST: api/Customers
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.
        [HttpPost]
        public async Task<ActionResult<Customer>> PostCustomer(Customer customer)
        {
            _context.Customer.Add(customer);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetCustomer", new { id = customer.ID }, customer);
        }

        // DELETE: api/Customers/5
        [HttpDelete("{id}")]
        public async Task<ActionResult<Customer>> DeleteCustomer(int id)
        {
            var customer = await _context.Customer.FindAsync(id);
            if (customer == null)
            {
                return NotFound();
            }

            _context.Customer.Remove(customer);
            await _context.SaveChangesAsync();

            return customer;
        }

        private bool CustomerExists(int id)
        {
            return _context.Customer.Any(e => e.ID == id);
        }
    }
}

这是我的 FetchCustomer.tsx

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import { Link, NavLink } from 'react-router-dom';

interface FetchCustomerData {
    customerList: CustomerData[];
    loading: boolean;
}

export class FetchCustomer extends React.Component<RouteComponentProps<any, any>, FetchCustomerData> {

    constructor(props: any) {
        super(props);
        this.state = { customerList: [], loading: true };
        fetch('api/Customers')
            .then(response => response.json() as Promise<CustomerData[]>)
            .then(data => {
                this.setState({ customerList: data, loading: true });
            });

        this.handleDelete = this.handleDelete.bind(this);
        this.handleEdit = this.handleEdit.bind(this);
    }

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

        return <div>
            <p>
                <Link to="api/Customer">Create New</Link>
            </p>
            {contents}
        </div>;
    }

    //Delete
    private handleDelete(id: number) {
        if (!confirm("Are you sure?" + id))
            return;
        else {
            fetch('api/Customers/5/' + id, {
                method: 'delete'
            }).then(data => {
                this.setState(
                    {
                        customerList: this.state.customerList.filter((rec) => {
                            return (rec.customerId != id);
                        })
                    });
            });
        }
    }

    private handleEdit(id: number) {
        this.props.history.push('api/Customers' + id);
    }

    private renderCustomerTable(customerList: CustomerData[]) {

        return <table className='table'>
            <p>This is table</p>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Address</th>
                    <th>Action</th>
                    <th>Action</th>
                </tr>
            </thead>
            <tbody>
                {
                    customerList.map(cust =>
                        <tr key={cust.customerId}>
                        <td></td>
                            <td>{cust.name}</td>
                            <td>{cust.address}</td>
                            <td>
                                <a className="action" onClick={(id) => this.handleEdit(cust.customerId)}>Edit</a>  |
                            <a className="action" onClick={(id) => this.handleDelete(cust.customerId)}>Delete</a>
                            </td>
                            </tr>
                )}
            </tbody>
        </table>;

    }

}

export class CustomerData {
    customerId: number = 0;
    name: string = "";
    address: string = "";
}

客户控制器中的 API 工作正常,这是输出。我api/Customers在 FetchCustomer 中使用过。

当我运行项目时,没有任何错误页面。它加载正常,但数据不可见:

在此处输入图像描述

当我运行 FetchCustomer 时,我得到了这个:

在此处输入图像描述

标签: reactjsasp.net-corereact-router

解决方案


您的代码中有几个问题:

  1. 正如上面的@Agney 评论,您需要在加载时将加载更改为false。否则,表格本身不会被渲染。
  2. 您的服务器返回一个具有属性的客户列表Id,而您的 TypeScript 客户端需要一个属性customerId。您需要将数组映射{id, name, address}到数组{customId, name, address}
  3. 您在 中嵌套了一个<p>元素<table/>,这是不正确的。
  4. handleEdit(id)函数推送 URL,如this.props.history.push('api/Customers' + id);. 您可能应该将其更改为('api/Customers/'+ id);
  5. 此外,您有 5 个<th>s,<thead><td>每行有 4 个 s。

要解决上述问题,您可以更改代码如下:

export class FetchCustomer extends React.Component<RouteComponentProps<any, any>, FetchCustomerData> {

    constructor(props: any) {
        super(props);
        this.state = { customerList: [], loading: true };
        fetch('api/Customers')
            .then(response => response.json())
            // Map each {id} to {customId}
            .then(data => data.map((d: any) => { return { ...d, customerId : d.id };}) )
            .then((data: CustomerData[]) => {
                // Change {loading} to false
                this.setState({ customerList: data, loading: false});
            });
        this.handleDelete = this.handleDelete.bind(this);
        this.handleEdit = this.handleEdit.bind(this);
    }

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

        return <div>
            <p>
                <Link to="api/Customer">Create New</Link>
            </p>
            {contents}
        </div>;
    }

    // Delete
    private handleDelete(id: number) {
        if (!confirm("Are you sure?" + id))
            return;
        else {
            fetch('api/Customers/5/' + id, {
                method: 'delete'
            }).then(data => {
                this.setState(
                    {
                        customerList: this.state.customerList.filter((rec) => {
                            return (rec.customerId != id);
                        })
                    });
            });
        }
    }

    private handleEdit(id: number) {
        this.props.history.push('api/Customers/' + id);
    }

    private renderCustomerTable(customerList: CustomerData[]) {

        return <div>
        <p>This is table</p>
        <table className='table'>
            <thead>
                <tr>
                    <th >ID</th>
                    <th>Name</th>
                    <th>Address</th>
                    <th>Action</th>
                </tr>
            </thead>
            <tbody>
                {
                    customerList.map(cust =>
                        <tr key={cust.customerId}>
                            <td>{cust.customerId}</td>
                            <td>{cust.name}</td>
                            <td>{cust.address}</td>
                            <td>
                                <a className="action" onClick={(id) => this.handleEdit(cust.customerId)}>Edit</a>  |
                                <a className="action" onClick={(id) => this.handleDelete(cust.customerId)}>Delete</a>
                            </td>
                        </tr>
                    )}
            </tbody>
        </table>
        </div>;

    }

}

推荐阅读