[英]Render a list of objects on a table object using axios calls : Rendering logic
我的組件應該在表格中呈現駕駛員列表,其中將潛水員姓名放在第一列,將拖拉機編號放在每行的第二列。 但是,如果對驅動程序表的引用返回null
,那么它會返回而不是拖拉機編號。 <td><Link to ={`/assign-tractor/${driver.id}`}> Assign Tractor </Link></li>)</td>
我如何實現這一目標?
下面是我的代碼在后端和前端的樣子。
我有一個用戶表,其中包含對拖拉機表的引用
Model:
public class User{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name ="user_id")
private Long id;
@OneToOne
@JoinColumn(name = "tractor_id", referencedColumnName = "tractor_id")
private Tractor tractor;
@OneToOne
@JoinColumn(name = "order_id", referencedColumnName = "order_id")
private Order order;
}
@Entity
@Table(name = "`order`")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="order_id")
private Long id;
private String orderNumber;
}
@Entity
@Table(name = "tractor")
public class Tractor {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name ="tractor_id")
private Long id;
private String tractorNumber;
}
Controller:
@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService) {
super();
this.userService = userService;
}
@GetMapping("drivers")
public List<User> allDrivers() {
return userService.findAllDriver();
}
@GetMapping("/id/{id}")
public User getUserByUserId(@PathVariable long id) {
return userService.findUserById(id);
}
}
@CrossOrigin
@RestController
@RequestMapping("/tractor")
public class TractorController {
private TractorService tractorService;
public TractorController(TractorService tractorService) {
super();
this.tractorService = tractorService;
}
@GetMapping("/tractors/{id}")
public Tractor getTractorById(@PathVariable Long id) {
return tractorService.FindTractorById(id).get();
}
}
反應前端
import React, { useState,Component} from 'react'
import axios from 'axios'
import './assignment-table.css';
import {withRouter} from 'react-router-dom';
class AssignmentTable extends Component {
constructor(props){
super(props);
this.state = {
drivers : [],
isLoggeIn: false,
tractorNumber: ""
}
}
componentDidMount(){
axios.get(`http://localhost:3000/project/user/users`)
.then(response => {
console.log(response)
this.setState({ drivers: response.data })
})
.catch( err => console.log(err))
//get tractor using user tractor reference, then assigns tractor number
/*
axios.get(`http://localhost:3000/project/tractor/${users.tractor}`)
.then(response => {
console.log(response)
this.setState({ tractorNumber: response.data.tractorNumber })
})
.catch( err => console.log(err))
}
*/
render() {
let drivers = this.state.drivers ? this.state.drivers.map((item, key) => {
return (
<tr>
<td key = {key}>{item.firstName} {item.lastName}</td>
</tr>)
}) : "No Avilable Driver"
return (
<table class="table">
<thead>
<tr>
<th scope="col">Driver Name</th>
<th scope="col">Tractor</th>
<th scope="col">Order</th>
</tr>
</thead>
<tbody>
{drivers}
</tbody>
</table>
);
}
}
export default withRouter (AssignmentTable);
我要復制的硬編碼引導程序版本:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Driver Name</th>
<th scope="col">Tractor Number</th>
<th scope="col">Order Number</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark Otto</td>
<td>123215</td>
<td>89562</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob Thornton</td>
<td>123254</td>
<td>564232</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry the Bird</td>
<td><a href="#">Assign Tractor</a></td>
<td><a href="#">Assign Order</a></td>
</tr>
</tbody>
</table>
</body>
</html>
所以有幾種方法可以解決這個問題。
“幼稚”的方法是為每條記錄向您的后端發出請求,然后當該記錄返回時,顯示信息。 但是,這可能是很多“緩慢”的請求,並且瀏覽器限制了您一次可以執行的請求數量。 這種類型的查詢稱為n+1
(在您的情況下2n+1
),從性能的角度來看通常被認為是一件壞事。 但這是可以做到的,而且相當容易。
另一種方法是僅通過一個查詢將所需的信息返回給前端。 因此,您將更改后端以在user/users
端點提供的信息中包含tractorNumber
和orderNumber
。 這使得前端非常簡單。
我也會考慮實際使用tractorNumber
和orderNumber
作為實際的 id,如果:
請注意,您不要只是將n+1
查詢移至后端,因為那樣緩慢會移到那里(但它可能仍然會更快)。 當您查找用戶端點的信息時,請確保它也加入了訂單和拖拉機信息,以便無需再次查找即可使用。
您可能不想更改后端的原因是它有點讓數據變得不那么“純粹”,因為現在您的端點正在同時返回多個模型的數據。 有時無論出於何種原因,您都無法更改后端。 您可能還決定此視圖值得擁有自己的特殊端點。
另一個可能有效的解決方案是在前端獲取所有拖拉機和訂單信息的列表並將其存儲,以便您可以查看緩存的信息,而不是每次都詢問后端。 但缺點是您必須存儲所有拖拉機和訂單信息,這可能會很多。 如果您決定對后端結果進行“分頁”,那么此解決方案將變得特別困難,但可能會奏效。
如果您確實決定使用“天真”方法 go,我建議將每一行提取到一個組件中,然后讓它有自己的查找,例如:
function getDrivers(){ // this would be the response in the real case /** return axios.get(`http://localhost:3000/project/user/users`).then(response => { console.log('drivers request:', response) return response.data }) */ // fake response for example return new Promise((resolve) => setTimeout(() => resolve([ {id: 11, firstName: "Dell", lastName: "McDonald", tractor_id: 123, order_id: 234}, {id: 12, firstName: "Bob", lastName: "Crockett", tractor_id: 145, order_id: 245}, {id: 13, firstName: "Joe", lastName: "Fresh", tractor_id: null, order_id: null} ]), 1000)) } function getTractorNumber(tractor_id) { //get tractor using user tractor reference, then assigns tractor number /* axios.get(`http://localhost:3000/project/tractor/${tractor_id}`).then(response => { console.log("tractor request:", response) return response.data.tractorNumber }) */ //Fake tractor response return new Promise((resolve) => setTimeout(() => resolve(`#T${tractor_id}-00`), Math.random()*5000)) } function getOrderNumber(order_id) { /* axios.get(`http://localhost:3000/project/order/${order_id}`).then(response => { console.log("order request:", response) return response.data.tractorNumber }) */ //Fake order response return new Promise((resolve) => setTimeout(() => resolve(`#O${order_id}`), Math.random()*5000)) } class AssignmentTable extends React.Component { constructor(props){ super(props); this.state = { drivers: [] } } componentDidMount(){ getDrivers().then(drivers => { this.setState({ drivers }) }).catch( err => console.log(err)) } render() { let drivers = this.state.drivers.length? this.state.drivers.map((item) => { return (<DriverRow driver={item} key={item.id} />) }): "No Available Drivers" return ( <table class="table"> <thead> <tr> <th scope="col">Driver Name</th> <th scope="col">Tractor</th> <th scope="col">Order</th> </tr> </thead> <tbody> {drivers} </tbody> </table> ); } } class DriverRow extends React.Component { constructor(...args) { super(...args) this.state = { tractorNumber: "loading...", orderNumber: "loading..." } } componentDidMount(){ getTractorNumber(this.props.driver.tractor_id).then(tractorNumber => { this.setState({ tractorNumber }) }).catch( err => console.log(err)) getOrderNumber(this.props.driver.order_id).then(orderNumber => { this.setState({ orderNumber }) }).catch( err => console.log(err)) } render() { const {firstName, lastName, tractor_id, order_id} = this.props.driver return (<tr> <td>{firstName} {lastName}</td> <td>{tractor_id? this.state.tractorNumber: <a href="#">Assign Tractor</a>}</td> <td>{order_id? this.state.orderNumber: <a href="#">Assign Order</a>}</td> </tr>) } } ReactDOM.render(<AssignmentTable />, document.getElementById('main'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <main id="main"/>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.