You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需轮询API:React+Laravel实现图书列表实时更新方案问询

可行解决方案:无刷新实时更新图书列表(React + Laravel)

针对你的需求,以下是几种无需轮询的实时更新方案,适配React前端和Laravel后端的技术栈:

方案1:WebSocket 双向通信(推荐)

利用WebSocket实现后端主动推送新图书数据到前端,这是实时交互场景的标准方案。Laravel官方提供Laravel Echo简化WebSocket集成,可搭配Pusher或Redis驱动。

后端实现步骤:

  1. 安装依赖:
composer require pusher/pusher-php-server
npm install laravel-echo pusher-js
  1. 创建图书创建事件:
// app/Events/BookCreated.php
namespace App\Events;

use App\Models\Book;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class BookCreated implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $book;

    public function __construct(Book $book)
    {
        $this->book = $book;
    }

    public function broadcastOn()
    {
        return new Channel('books');
    }
}
  1. 在图书新增接口中触发事件:
// 图书新增控制器方法示例
$book = Book::create($request->validated());
event(new BookCreated($book));
return response()->json($book);

前端实现(ViewAllBooks.jsx):

import { useEffect, useState } from 'react';
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

window.Pusher = Pusher;

const ViewAllBooks = () => {
    const [books, setBooks] = useState([]);

    useEffect(() => {
        // 初始化Echo连接
        const echo = new Echo({
            broadcaster: 'pusher',
            key: process.env.REACT_APP_PUSHER_APP_KEY,
            cluster: process.env.REACT_APP_PUSHER_APP_CLUSTER,
            forceTLS: true
        });

        // 监听books频道的BookCreated事件
        echo.channel('books')
            .listen('BookCreated', (e) => {
                // 将新图书插入列表头部
                setBooks(prev => [e.book, ...prev]);
            });

        // 组件卸载时断开连接
        return () => echo.disconnect();
    }, []);

    // 初始加载图书列表的逻辑...

    return (
        <div>
            {/* 图书列表渲染代码 */}
        </div>
    );
};

export default ViewAllBooks;

方案2:Server-Sent Events(SSE)单向推送

SSE是HTTP协议的扩展,支持后端单向向前端推送数据,实现比WebSocket更简单,适合仅需后端主动推送的场景。

后端实现(Laravel路由):

// routes/api.php
use App\Models\Book;
use Illuminate\Http\Response;

Route::get('/books/sse', function () {
    $response = new Response();
    $response->header('Content-Type', 'text/event-stream');
    $response->header('Cache-Control', 'no-cache');
    $response->header('Connection', 'keep-alive');

    while (true) {
        $lastBookId = request()->query('last_id', 0);
        $newBooks = Book::where('id', '>', $lastBookId)->get();

        if ($newBooks->isNotEmpty()) {
            foreach ($newBooks as $book) {
                echo "data: " . json_encode($book) . "\n\n";
                ob_flush();
                flush();
            }
        }

        sleep(2); // 控制轮询间隔,避免CPU占用过高
    }
});

前端实现(ViewAllBooks.jsx):

import { useEffect, useState } from 'react';

const ViewAllBooks = () => {
    const [books, setBooks] = useState([]);

    useEffect(() => {
        const lastBookId = books.length ? books[0].id : 0;
        const eventSource = new EventSource(`/api/books/sse?last_id=${lastBookId}`);

        eventSource.onmessage = (event) => {
            const newBook = JSON.parse(event.data);
            setBooks(prev => [newBook, ...prev]);
        };

        eventSource.onerror = () => eventSource.close();

        return () => eventSource.close();
    }, [books]);

    // 初始加载图书列表的逻辑...

    return (
        <div>
            {/* 图书列表渲染代码 */}
        </div>
    );
};

export default ViewAllBooks;

方案3:前端跨页广播 + 按需拉取数据

如果不想依赖WebSocket/SSE,可利用浏览器的Broadcast Channel API实现跨页面通信,在新增图书成功后通知列表页主动拉取最新数据。

前端实现(AddBook.jsx):

const AddBook = () => {
    const handleSubmit = async (formData) => {
        const response = await fetch('/api/books', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(formData)
        });

        if (response.ok) {
            // 创建广播频道发送更新通知
            const channel = new BroadcastChannel('book-updates');
            channel.postMessage({ type: 'BOOK_ADDED' });
            channel.close();
        }
    };

    return (
        <div>
            {/* 图书新增表单 */}
        </div>
    );
};

export default AddBook;

前端实现(ViewAllBooks.jsx):

import { useEffect, useState } from 'react';

const ViewAllBooks = () => {
    const [books, setBooks] = useState([]);

    // 拉取图书列表的通用方法
    const fetchBooks = async () => {
        const response = await fetch('/api/books');
        const data = await response.json();
        setBooks(data);
    };

    useEffect(() => {
        fetchBooks();

        // 监听跨页广播
        const channel = new BroadcastChannel('book-updates');
        channel.onmessage = () => fetchBooks();

        return () => channel.close();
    }, []);

    return (
        <div>
            {/* 图书列表渲染代码 */}
        </div>
    );
};

export default ViewAllBooks;

方案对比

  • WebSocket:双向通信,支持复杂交互(如实时删除/修改),但需要额外配置服务(Pusher/Redis)。
  • SSE:单向通信,实现简单,无需额外服务,但仅支持文本数据,旧浏览器兼容性稍差。
  • 前端广播+按需拉取:纯前端实现,无需后端额外配置,但仅当两个页面同时打开时生效,需主动拉取数据。

内容的提问来源于stack exchange,提问作者Mohamed Mushkir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 17:33:26