将RShiny篮球数据可视化应用迁移至React:数据接入方案咨询
Hey there! Let's break down how to migrate your basketball data visualization app from R Shiny to React, and get that data flowing smoothly. I've worked through similar stack transitions, so here's a step-by-step approach tailored to your existing setup:
Your existing scraper.R is already doing the heavy lifting—no need to rewrite it in another language. First, adjust it to output data in a format React can easily consume:
- Export to JSON/CSV: After scraping, save your cleaned data to a JSON file (using
jsonlite::write_json()) or CSV in a directory that's accessible to your backend. Keep your existing scheduler/cron job that runs the scraper daily intact. - Avoid Shiny-specific objects: Make sure the output data is plain tabular/structured data, not Shiny reactive values.
Directly reading files from React can get messy (file locks, caching issues, no authentication if needed). Instead, wrap your data access with a simple API. Since you're comfortable with R, Plumber is the perfect tool here—it lets you turn R functions into REST APIs with minimal code.
Here's a quick example Plumber endpoint (api.R):
#* @get /basketball-data function() { # Load the latest data from your scraper's output data <- jsonlite::read_json("/path/to/your/scraper-output.json") return(data) }
Run the Plumber API with:
library(plumber) pr("api.R") %>% pr_run(port=8000)
Now React can hit http://your-ec2-ip:8000/basketball-data to get fresh JSON data.
On the React side, use standard data-fetching tools to pull in the data. For a daily-updated app, a simple scheduled fetch works great:
- Use
fetchoraxiosto call your Plumber API. - Use React's
useEffecthook to load data on component mount, and set a timer to refresh it daily (or on user action). - For visualization, use libraries like Recharts or D3.js—both play nicely with React and handle structured data well.
Example React snippet:
import { useEffect, useState } from 'react'; import axios from 'axios'; import { BarChart, Bar, XAxis, YAxis } from 'recharts'; function BasketballStats() { const [data, setData] = useState([]); useEffect(() => { const fetchData = async () => { const response = await axios.get('http://your-ec2-ip:8000/basketball-data'); setData(response.data); }; fetchData(); // Refresh every 24 hours const interval = setInterval(fetchData, 86400000); return () => clearInterval(interval); }, []); return ( <BarChart width={800} height={400} data={data}> <XAxis dataKey="playerName" /> <YAxis /> <Bar dataKey="points" fill="#2196F3" /> </BarChart> ); }
Your existing EC2 instance can still host everything—just tweak what runs on it:
- Serve React: Build your React app with
npm run build, then serve the static files using Nginx (replace Shiny Server if you don't need it anymore, or run both on different ports). - Run Plumber API: Set up the Plumber script to run as a background service (use
systemdon Linux) so it stays up even if you log out of the EC2 instance. - Optional: Dockerize: For easier deployment and scaling, wrap your React app and Plumber API in separate Docker containers. This keeps dependencies isolated and makes it simple to update either part without breaking the other.
If your scraper is collecting more data over time, switching from flat files to a database will make data management more reliable:
- Use SQLite (lightweight, no server needed) or PostgreSQL (for scaling) in your R scraper to insert/update data directly.
- Update your Plumber API to query the database instead of reading files—this avoids file I/O issues and lets you do more complex data filtering (e.g., fetching stats for a specific player/team directly from the API).
Start small: first get your scraper outputting accessible JSON, build a simple React component to fetch and display it, then iterate on the API and deployment. Since you already know R, leaning into Plumber is a great way to reuse your existing skills without rewriting everything from scratch.
内容的提问来源于stack exchange,提问作者Canovice

