reactjs - 如何在 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 时,我得到了这个:
解决方案
您的代码中有几个问题:
- 正如上面的@Agney 评论,您需要在加载时将加载更改为false。否则,表格本身不会被渲染。
- 您的服务器返回一个具有属性的客户列表
Id
,而您的 TypeScript 客户端需要一个属性customerId
。您需要将数组映射{id, name, address}
到数组{customId, name, address}
- 您在 中嵌套了一个
<p>
元素<table/>
,这是不正确的。 - 该
handleEdit(id)
函数推送 URL,如this.props.history.push('api/Customers' + id);
. 您可能应该将其更改为('api/Customers/'+ id);
- 此外,您有 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>;
}
}
推荐阅读
- java - 有没有办法通过异常处理重复消息,直到输入正确?
- java - 在春季批处理中,我们如何将处理后的文件移动到另一个文件夹,我正在使用 MultiResourceItemReader 和块处理
- python - FFT 弹奏单个钢琴音符时的其他频率是什么
- testing - TestCafe :当测试在 TestCafe 中运行时,当用户移动到另一个窗口或应用程序时,测试执行挂起
- javascript - express 中是否有任何功能可以结束 express 中的特定路由方法而不进一步执行?
- c++ - 视觉工作室说 CMake 二进制部署到远程机器开始了。部署完成后,CMake 生成将自动继续
- python - discord.py 从 .json 文件中获取服务器前缀
- javascript - 单击时水平滚动 div 元素
- python - 将 Django Web 界面与 Python 连接起来
- erlang - Erlang:如何断言匹配 IoDevice 值?