React-Slingshot 全栈集成教程6 步把 React 前端和 Node.js 后端 API 打通【免费下载链接】react-slingshotReact Redux starter kit / boilerplate with Babel, hot reloading, testing, linting and a working example app built in项目地址: https://gitcode.com/gh_mirrors/re/react-slingshot浏览器控制台里一行红色报错CORS policy: No Access-Control-Allow-Origin。页面能渲染表单能填唯独一提交就被拦下来。如果你的前端项目是 React-SlingshotReact Redux starter kit这篇教程带你按真实联调顺序把前端集成后端的全栈链路走通本地双服务跑起来 → axios 请求层 → Express 最小后端 → Redux 数据流 → 生产构建注入 API 地址终点是「页面按钮一按数据从后端 4000 端口的接口流进 store 并渲染出来」。先复现一次前端为什么调不通后端接口联调卡在第一步时90% 的情况不是代码写错而是两个服务压根没对齐。拿 React-Slingshot 来说它的开发服务器由 tools/srcServer.js 驱动默认占用3000 端口同时 BrowserSync 的 UI 面板占掉3001——这里第一个坑就埋好了如果你习惯让后端也跑 3001两个服务会直接打架。先明确本文的终点状态后面每一步都以它为验收标准前端跑在http://localhost:3000后端跑在http://localhost:4000打开页面时DevTools 的 Network 面板里能看到对/api/fuel/rates的请求返回 200Redux DevTools 里能看到FETCH_FUEL_RATES_SUCCESS这个 action 被派发payload 是接口返回的 JSON。后面每一步都围绕这个状态推进任何一步做完都可以对照检查不用等全部搭完才发现问题。画出链路请求从页面到后端的 6 个节点动手前把链路在脑子里过一遍出问题时才能快速定位是哪一段断的本地环境(3000/4000) → 请求层(src/utils/api.js) → Express 后端(4000) ↑ ↓ 生产构建(DistPM2) ← 验证(curl/jest/DevTools) ← 状态流(thunk action → reducer → 容器组件)用一句话串起来axios 实例负责怎么发thunk action 负责什么时候发、发完往 store 里放什么reducer 负责数据落到 state 的哪个位置容器组件负责从 state 里取出来渲染。环境、请求层、后端、状态流、验证、上线后文按这个顺序逐段搭建每段都有可复制的代码和一句验证方法。克隆仓库并跑通最小环境先把前端自身跑起来确认工具链没问题再谈联调。# 克隆 starter kit仓库自带示例应用 FuelSavings正好当联调载体 git clone https://gitcode.com/gh_mirrors/re/react-slingshot cd react-slingshot npm install # npm start 会同时起测试、lint 和开发服务器见 package.json 里 concurrently 的定义 npm start预期看到什么浏览器自动打开http://localhost:3000显示 FuelSavings 示例表单终端里能看到 test:watch、lint:watch、open:src 三路输出。如果卡在npm install先按 docs/FAQ.md 里 How do I debug? 一节排查。跑通之后花两分钟定位三个关键文件后面改哪段都靠它们文件作用后面会动它吗package.jsonstart/build等脚本、依赖清单只加一个 axioswebpack.config.dev.js / webpack.config.prod.js开发/生产构建process.env注入点都加一行 API 地址src/store/configureStore.jsRedux store 装配thunk 中间件已注册不动注意 src/store/configureStore.js 里 dev 和 prod 两条分支都已经挂上了thunk——这意味着异步 action 不用额外配置中间件这是这个 starter 白送的好处很多教程会在这一步劝退你。最后补一个 starter 里没有的依赖npm install axios验证方式npm start的 lint:watch 输出里没有新增报错终端重新编译完成即可说明依赖图正常。环境干净了接下来把怎么发请求收敛到一个地方避免每个组件各自 new 一个 axios。封装统一的请求层axios 实例加认证拦截器新建src/utils/api.jsimport axios from axios; // baseURL 由 webpack 的 DefinePlugin 注入dev/prod 配置里各加一行见上线一节 // 兜底值保证本地开发没配环境变量时也能直连 4000 端口的后端 const api axios.create({ baseURL: process.env.API_URL || http://localhost:4000/api, timeout: 5000, headers: {Content-Type: application/json}, }); // 请求拦截器本地有登录态时自动附带 Bearer token // 业务代码里就不用每个请求手写 Authorization 头 api.interceptors.request.use(config { const token localStorage.getItem(authToken); if (token) { config.headers.Authorization Bearer ${token}; } return config; }); // 响应拦截器非 2xx 统一抛错action 里只写 catch 分支 api.interceptors.response.use( response response, error Promise.reject(error) ); export default api;为什么集中管理baseURL 换环境只改一处token 注入、错误归一化只写一遍将来换掉 axios 或加重试逻辑改动范围被锁死在这个文件里。验证方式npm start触发热更新lint:watch 输出无新报错文件被引用后构建能正常通过下一节马上就会引用它。请求层就位后另一端该立起来了——一个十分钟能搭完、curl 能打通的 Express 服务。搭一个十分钟能 curl 通的 Express 最小后端后端刻意放在前端仓库外面两个项目独立部署、独立生命周期。# 与 react-slingshot 平级建目录 mkdir fuel-api cd fuel-api npm init -y npm install express corsserver.js保持最小化只保留联调必需的三样东西// server.js const express require(express); const cors require(cors); const app express(); // 只放行前端的真实来源。开发期是 localhost:3000 // 生产环境换成前端域名不要图省事写 *带 cookie 时不安全 app.use(cors({origin: http://localhost:3000})); app.use(express.json()); // 解析 JSON 请求体处理 POST 时必备 // 最小只读接口返回当前油价和前端 FuelSavings 场景对得上 app.get(/fuel/rates, (req, res) { res.json({ gasoline: 3.89, diesel: 4.12, lastUpdated: new Date().toISOString(), }); }); // 端口走环境变量默认 4000——避开前端占用的 3000/3001 const PORT process.env.PORT || 4000; app.listen(PORT, () console.log(API listening on ${PORT}));启动并验证node server.js curl http://localhost:4000/api/fuel/rates预期看到什么curl 返回一段 JSON包含gasoline:3.89和时间戳。到这一步后端这一段就算通了——先保证 curl 能通再谈浏览器能不能通排查顺序反了会浪费一倍时间。后端有了最后一段是把接口数据接进 Redux让组件消费它。把 Redux 异步 action 接到容器组件上数据流走 starter 既有的四件套常量 → action → reducer → 容器组件。逐段加每段都不超过五行。1常量在 src/constants/actionTypes.js 追加两个export const FETCH_FUEL_RATES_SUCCESS FETCH_FUEL_RATES_SUCCESS; export const FETCH_FUEL_RATES_FAILURE FETCH_FUEL_RATES_FAILURE;2异步 action在 src/actions/fuelSavingsActions.js 里追加一个 thunk。starter 里的saveFuelSavings已经是 thunk 写法注释里写着 thunks allow for pre-processing actions, calling apis这里照同样的形状扩展import api from ../utils/api; import * as types from ../constants/actionTypes; // thunk 里发请求成功把数据 dispatch 回 store失败派发错误 action export function fetchFuelRates() { return async dispatch { try { const {data} await api.get(/fuel/rates); dispatch({ type: types.FETCH_FUEL_RATES_SUCCESS, payload: data, }); } catch (error) { dispatch({ type: types.FETCH_FUEL_RATES_FAILURE, error: error.message, }); } }; }3reducer在 src/reducers/fuelSavingsReducer.js 的 switch 里加一个分支保持现有objectAssign的不可变写法case FETCH_FUEL_RATES_SUCCESS: // 接口数据落到 state.fuelSavings.fuelRates组件从这里读 return objectAssign({}, state, {fuelRates: action.payload});4容器组件在 src/components/containers/FuelSavingsPage.js 里把新 action 绑进 dispatch并在挂载时触发一次拉取componentDidMount() { this.props.actions.fetchFuelRates(); // 页面挂载时向 4000 端口要一次油价 } // mapDispatchToProps 里把 action 绑上 dispatchstarter 现成写法是 // bindActionCreators直接 import fetchFuelRates 一起绑即可验证方式npm start热更新后刷新页面DevTools → Redux 面板应出现FETCH_FUEL_RATES_SUCCESSstate.fuelSavings.fuelRates里有gasoline: 3.89。到这里整条链路在开发环境闭环了。能跑起来不等于稳下一步用 mock 测试锁住行为再演练一遍双服务启动。用 mock 测试和双服务启动验证全链路先补一个单测把成功后 dispatch 带数据的 action这个行为锁死。新建src/actions/fuelSavingsActions.spec.jsstarter 的惯例是测试文件与被测文件同目录见 docs/FAQ.mdimport api from ../utils/api; import {fetchFuelRates} from ./fuelSavingsActions; import * as types from ../constants/actionTypes; // 不真的发 HTTP 请求整个 api 模块 mock 掉 jest.mock(../utils/api); describe(fetchFuelRates, () { it(成功后 dispatch 带接口数据的 action, async () { const mockRates {gasoline: 3.89, diesel: 4.12}; api.get.mockResolvedValue({data: mockRates}); const dispatch jest.fn(); await fetchFuelRates()(dispatch); // 断言派发的是 success 类型 完整 payload expect(dispatch).toHaveBeenCalledWith({ type: types.FETCH_FUEL_RATES_SUCCESS, payload: mockRates, }); }); });npx jest fuelSavingsActions预期看到什么Tests: 1 passed。这个测试保证后端挂掉时行为可预期——失败走FETCH_FUEL_RATES_FAILURE分支不会让组件白屏。再演练一遍完整的双服务启动真实联调非 mock# 终端 1前端3000 页面 / 3001 BrowserSync UI cd react-slingshot npm start # 终端 2后端4000 node fuel-api/server.js预期看到什么打开http://localhost:3000DevTools → Network 里/api/fuel/rates状态 200Redux 面板出现对应 action。如果 Network 里是红色 CORS 报错先查后端cors({origin})里写的来源和浏览器地址栏是否一字不差——这是本联调流程里最高频的一个坑。本地稳定之后剩下的事就是把环境差异固化到构建里。生产构建注入 API 地址并部署上线React-Slingshot 生产构建的环境变量入口是 webpack.config.prod.js 顶部现成的GLOBALS对象被DefinePlugin消费。加一行const GLOBALS { process.env.NODE_ENV: JSON.stringify(production), // 构建时写死生产 API 地址随 bundle 一起发布 process.env.API_URL: JSON.stringify(https://your-api-domain.com/api), __DEV__: false };开发侧同理在 webpack.config.dev.js 的plugins数组里补一个new webpack.DefinePlugin({ // 开发环境指向本地 4000 端口的 Express process.env.API_URL: JSON.stringify(http://localhost:4000/api), }),为什么不用 .env 文件这套 starter 的构建里没有接 dotenvprocess.env里的值只有走DefinePlugin才会被替换进 bundle直接读.env是读不到的。构建与部署# 构建prebuild 会先跑 lint 全量测试 清理 dist再输出带 contenthash 的产物 npm run build # 前端dist/ 交给任意静态服务器Nginx 即可 # 或先本地预览npm run open:dist # 后端PM2 托管进程挂掉自动拉起 pm2 start fuel-api/server.js --name fuel-api pm2 save预期看到什么dist/下出现bundle.[hash].js和 HTML把dist/丢给静态服务器后浏览器 Network 面板里对生产 API 域名的请求返回 200且响应头里有Access-Control-Allow-Origin指向你的前端域名。最后用npm start的 test:watch 和 CI 里的npm run test兜底确认生产构建前测试全绿。到这一步功能闭环了但上线前后还有几个高频坑值得单独列出来。上线前过一遍这份坑清单联调踩过的坑按出现频率排个序每条都对应本文前面某个环节端口撞车前端占 3000BrowserSync UI 占 3001后端默认 3001 必挂。改后端端口比改 starter 省事。CORS origin 别写*带认证头或 cookie 时会被浏览器拒绝生产环境 origin 必须换成前端真实域名和部署地址一字不差。thunk 已经注册好了src/store/configureStore.js 的 dev/prod 两条中间件链里都有thunk异步 action 直接写别再叠 redux-promise 之类的中间件。派生数据用选择器接口数据进 store 之后组件里反复算同一份派生值时换成 reselect 缓存选择器别在 render 里重复计算。localStorage 里的 token 防君子不防小人它对所有 JS 可见安全要求高时改用 httpOnly cookie 后端校验拦截器那层只负责透传。回头看这 6 步其实就一句话请求层收口、后端最小化、状态流走 starter 现成的 thunk 通道、环境差异交给 DefinePlugin。整条链路每一段都独立可验证——curl 通后端、jest 锁行为、DevTools 看 store哪段红了修哪段不用猜。想继续深入docs/FAQ.md 里有 How do I deploy this? 和 How do I debug? 两节前者讲 dist 产物的部署细节后者含 VS Code 调试配置比本文的口径更细。【免费下载链接】react-slingshotReact Redux starter kit / boilerplate with Babel, hot reloading, testing, linting and a working example app built in项目地址: https://gitcode.com/gh_mirrors/re/react-slingshot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
TranslucentTB 任务栏透明美化,3 分钟上手 TranslucentTB 任务栏透明美化,3 分钟上手 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB
一张精心挑选的壁纸,底… · 2026/11/6 7:43:31
Folia 全屏歌词播放器安装教程:Windows/macOS/Linux 三端 4 步跑通 Folia 全屏歌词播放器安装教程:Windows/macOS/Linux 三端 4 步跑通 【免费下载链接】folia-major 专注于绚丽的歌词动画效果的本地音乐/navidrome/第三方多平台在线音乐播放器 A multi-platform music player for local files, Navidrome, and online streaming ser… · 2026/11/6 7:43:31
python程序写完怎么运行 程序写完怎么运行如何在 中运行程序如果想要去让这个程序运行起来的话, 其实是有那么两种主要的方法可以去进行选择的。1. 大家在使用那个解释器的时候, 需要进行相关的解释。你需要在终端或者命令提示窗体里面执行操作, 把下面给出的这条指令敲进去输入。python script.py这里… · 2026/11/6 7:42:31
电工证是职业职称吗网上查询怎么操作 电工证是职业职称吗网上查询怎么操作 证书过期了不知道怎么复审延期,这种情况在很多特种作业人员身上都出现过,尤其是像你这样的商丘房建工程从业者,每天和电打交道,但一不小心就可能因为疏忽错过复审时间,影响工作进度甚至带来安全风险。… · 2026/11/6 21:35:47
电工证昌吉多久拿证?找工作必备证书怎么考 电工证昌吉多久拿证?找工作必备证书怎么考 找工作缺证?电工证昌吉怎么考?别急,这篇讲透全过程! 你是不是正愁找不到合适的工作?单位要求持证上岗,而你手里却连个电工证都没有?别担心,电工证昌吉已经不是什么新鲜事,但你得知道 多久拿证… · 2026/11/6 21:35:47
叙永考电工证在哪考?实操考试心里没底怕挂科?看这里全搞定 叙永考电工证在哪考?实操考试心里没底怕挂科?看这里全搞定 实操考试心里没底怕挂科?叙永考电工证到底在哪考?很多小伙伴一提到特种作业证,尤其是电工证,第一反应就是考试难、挂科率高、流程复杂,搞得整个人都没了信心。今天咱们就从郑州应届工程类毕业… · 2026/11/6 21:35:46
宁强县高压电工证在哪考 选错地方花冤枉钱 宁强县高压电工证在哪考 选错地方花冤枉钱 你是不是也在为【宁强县高压电工证】在哪考发愁?网上一搜满是培训机构,真假难辨,稍不留神就可能被坑了。今天咱们不绕弯子,直接说重点,帮你搞清楚【宁强县高压电工证】到底是怎么考的、该去哪报、值不值得考,… · 2026/11/6 21:35:46
佛山电工证考证怎么报?学历不高也能考!全国通用证件怎么拿 佛山电工证考证怎么报?学历不高也能考!全国通用证件怎么拿 你是不是也担心自己学历不高,连佛山电工证考证都报不上名?其实,这事儿没那么难,只要方法对,全国通用的电工证照样能拿到手。今天就给你讲讲怎么操作,避坑又高效。… · 2026/11/6 21:35:46
武汉哪里能办理电工证 低压电工证含金量如何看 武汉哪里能办理电工证 低压电工证含金量如何看 学历不高怕报不上名?别急,今天咱们就来说说 武汉哪里能办理电工证 ,重点讲讲低压电工证的 含金量 ,以及你真正需要知道的那些事。… · 2026/11/6 21:34:46
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:29:23
三菱PLC数据采集到数据库的时序设计:Python+MC协议实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11
ASIC主模式RTL设计:状态机与三态驱动的流片级实现 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11
STM32嵌入式C++开发:GDB调试与Renode仿真实战指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:29:23