網頁

2021/7/28

React fetch data from Spring Boot REST API

React從Spring Boot REST API獲取資料範例。


範例環境:

  • Spring Boot 2
  • React 17


Spring Boot

建立Spring Boot應用程式網址為http:localhost:8080

新增一個DemoController提供API GET | /employees用來給React取得Employee資料。

後端Spring Boot網址為http://localhost:8080與前端React http://localhost:3000屬於不同源的網路資源,瀏覽器預設會限制CORS(Cross-Origin Resource Sharing),因此Server端必須設定允許CORS,Spring Boot要在Controller method前加上@CrossOrigin,否則React無法從Spring Boot REST API取資料。

DemoController

package com.abc.demo.controller;

import com.abc.demo.model.Employee;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

@RestController
public class DemoController {

    @CrossOrigin
    @GetMapping("/employees")
    public List<Employee> getEmployees() {
        return Arrays.asList(
                new Employee(1, "John", 33),
                new Employee(2, "Mary", 28),
                new Employee(3, "Tony", 45)
        );
    }
}

API回傳的Employee結構如下。

Employee

package com.abc.demo.model;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Employee {
    private long id;
    private String name;
    private int age;
}

使用cURL或直接在瀏覽器測試API回傳以下結果。

[{"id":1,"name":"John","age":33},{"id":2,"name":"Mary","age":28},{"id":3,"name":"Tony","age":45}]


React

建立React應用程式網址為http:localhost:3000

App.js內容如下,建立ComponentTableROW

App.js

import { useEffect, useState } from "react";
import "./App.css";

import * as React from 'react';

function App() {
  return (
    <Table>
      <Row />
    </Table>
  );
}

const Row = () => {
  const [employees, setEmployees] = useState([])
  useEffect(() => {
    fetch("http://localhost:8080/employees")
    .then(response => response.json())
    .then(data => setEmployees(data))
  }, [])

  return (
    <>
      {
        employees.map((emp, i) => {
          return (
            <tr key={emp.id}>
              <td>{emp.id}</td>
              <td>{emp.name}</td>
              <td>{emp.age}</td>
            </tr>
          );
        })
      }
    </>
  )
};

const Table = (props) => {
  return (
    <table>
      <thead>
        <tr>
          <th>ID</th>
          <th>Name</th>
          <th>Age</th>
        </tr>
      </thead>
      <tbody>{props.children}</tbody>
    </table>
  );
};

export default App;

ROW中在Hook API useEffect()使用JavaScript的fetch()呼叫Spring Boot的GET | /employees取得response後轉成json呼叫setEmployees()更新Row.state.employees狀態useEffect()第二個參數為dependency array,使用一個空陣列避免因狀態改變造成的無窮迴圈。


測試

在瀏覽器輸入http://localhost:3000回傳的table html內容如下。

<table>
  <thead>
    <tr>
      <th>ID</th>
      <th>Name</th>
      <th>Age</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>John</td>
      <td>33</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Mary</td>
      <td>28</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Tony</td>
      <td>45</td>
    </tr>
  </tbody>
</table>

參考github


沒有留言:

張貼留言