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

如何在React Material-table中添加自定义列实现行数据保存至MongoDB

实现步骤及修改代码

前端部分修改

你不需要修改接口返回的原始数据,Material-Table的列配置支持自定义渲染,直接新增操作列即可,修改后的前端代码如下:

import React, {useState, useEffect} from 'react'
import MaterialTable from 'material-table'
import axios from "axios";

const DataTable = () => {
  const [tableData, setTableData] = useState([]);
  const [showMyStocks, setShowMyStocks] = useState(false);
  const [myStocks, setMyStocks] = useState([]);
  const columns = [
    {title: 'NAME', field: 'name', width: 200},
    {title: 'SYMBOL', field: 'symbol', width: 200},
    {title: 'MARKET CAP', field: 'market_cap', width: 200},
    {title: 'CURRENT PRICE', field: 'price', width: 200},
    // 新增自定义操作列,不需要修改原接口数据
    {
      title: '操作',
      width: 150,
      render: rowData => <button onClick={() => handleSave(rowData)}>保存到自选</button>
    }
  ]

  // 保存股票到后端接口
  const handleSave = async (rowData) => {
    try {
      // 按需提取要存储的字段,避免冗余
      const saveData = {
        name: rowData.name,
        symbol: rowData.symbol,
        market_cap: rowData.market_cap,
        price: rowData.price
      }
      await axios.post('/api/stocks/save', saveData)
      alert('保存成功')
    } catch (err) {
      console.error('保存失败', err)
      // 重复保存的提示可以根据后端返回的错误码自定义
      alert(err.response?.data?.msg || '保存失败,请重试')
    }
  }

  // 获取已保存的自选股票
  const fetchMyStocks = async () => {
    const res = await axios.get('/api/stocks/my')
    setMyStocks(res.data)
    setShowMyStocks(true)
  }

  useEffect(() => {
        axios
          .get(
            "https://api.nomics.com/v1/currencies/ticker?key=xyz&interval=1d,30d&convert=USD&per-page=100"
          )
          .then((res) => {
            console.log(res);
            setTableData(res.data);
          })
      }, []);

  return (
      <div>
        <button onClick={fetchMyStocks} style={{margin: '20px 14%'}}>查看我的自选股票</button>
        <div >
          <MaterialTable style={{height: 400, width: '70%', left: '14%', top: 20}}
            data={tableData}
            columns={columns}
            title={"Stock Details Table"}
            options={{
              search: true
            }}
          />
        </div>
        {/* 自选股票弹窗,也可以单独做页面展示 */}
        {showMyStocks && (
          <div style={{position: 'fixed', top: '10%', left: '10%', width: '80%', background: '#fff', padding: '20px', boxShadow: '0 0 10px #ccc'}}>
            <button onClick={() => setShowMyStocks(false)} style={{float: 'right'}}>关闭</button>
            <MaterialTable
              data={myStocks}
              columns={columns.slice(0,4)} // 复用原有列配置,去掉操作列
              title={"我的自选股票"}
            />
          </div>
        )}
      </div>
  )
}

export default DataTable

后端MERN接口实现

1. 定义MongoDB数据模型

新建models/Stock.js文件,定义股票存储结构:

const mongoose = require('mongoose')
const stockSchema = new mongoose.Schema({
  name: String,
  // 加唯一索引避免重复保存同一只股票
  symbol: { type: String, unique: true },
  market_cap: Number,
  price: Number,
  saveTime: { type: Date, default: Date.now }
})
module.exports = mongoose.model('Stock', stockSchema)

2. 编写接口路由

新建routes/stocks.js文件,编写两个接口:

const express = require('express')
const router = express.Router()
const Stock = require('../models/Stock')

// 保存自选股票接口
router.post('/save', async (req, res) => {
  try {
    const stock = new Stock(req.body)
    await stock.save()
    res.status(200).json({ code: 0, msg: '保存成功' })
  } catch (err) {
    if (err.code === 11000) {
      return res.status(400).json({ code: 1, msg: '该股票已在自选列表中' })
    }
    res.status(500).json({ code: 1, msg: '保存失败' })
  }
})

// 获取所有已保存自选股票接口
router.get('/my', async (req, res) => {
  const stocks = await Stock.find().sort({ saveTime: -1 })
  res.status(200).json(stocks)
})

module.exports = router

3. 挂载路由

在后端入口文件中挂载路由,确保和前端请求的地址匹配:

// 要提前完成MongoDB连接配置
app.use('/api/stocks', require('./routes/stocks'))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 05:15:03