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

React中Select标签特定选项值获取及Modal订单表单疑问

经纪商模拟器开发问题

我正在开发一款经纪商模拟器,有两个核心需求:

  • 根据Select标签选择的不同货币对,获取对应的实时汇率值
  • 不确定是否需要在Modal对话框中使用Form组件,将最终的订单信息发送到其他标签页

目前遇到的问题:尝试了多种值的传递方式都没解决,Modal对话框要么拿不到值,要么值不随选中的货币对变化,要么只显示某一个货币对的固定值。


初始代码

import React, {useState} from "react";
import './select.css'
import Modal from "../popup/modal"
import { useEffect } from "react";

const Select = () => {

    
    const [value, setValue] = useState("");

    const [usdrub, setUsdrub] = useState(Math.random() * (64-61) + 61);
    useEffect(() => {
      const interval = setInterval(() => {
        setUsdrub(Math.random() * (64-61) + 61);
      }, 10000);
      return () => clearInterval(interval);
    }, [])

    const [rubusd, setRubusd] = useState(Math.random() * 2);
    useEffect(() => {
      const interval = setInterval(() => {
        setRubusd(Math.random() * 2);
      }, 10000);
      return () => clearInterval(interval);
    }, [])



    function changeSelect() {
        setValue(value)
    }
    const [modalActive, setModalActive] = useState(false)



    return (
        <div>
        <select onChange={changeSelect}>
        <option name="USD/RUB" value={usdrub}>USD/RUB</option>
        <option name="RUB/USD" value={rubusd}>RUB/USD</option>
        </select>
        <div className="Curr">
          <div className="Buy" name="buy"> <button className="Buy" type="btn" onClick={() => setModalActive(true)}>BUY {value + 1} </button>
          </div>
          <div className="Sell" name="sell"><button className="Sell" type="btn"  onClick={() => setModalActive(true)}>SELL {value}</button></div>
          </div>
          <Modal active={modalActive} setActive={setModalActive} price={usdrub + 1}/>
        </div>
        
    )
}

export default Select

更新后的代码

import React, {useState} from "react";
import './select.css'
import Modalbuy from "../popup/Modalbuy"
import Modalsell from "../popup/Modalsell"
import { useEffect } from "react";

const Select = () => {

    
    const [value, setValue] = useState("");

    const [usdrub, setUsdrub] = useState(Math.random() * (64-61) + 61);
    useEffect(() => {
      const interval = setInterval(() => {
        setUsdrub(Math.random() * (64-61) + 61);
      }, 10000);
      return () => clearInterval(interval);
    }, [])

    const [rubusd, setRubusd] = useState(Math.random() * 2);
    useEffect(() => {
      const interval = setInterval(() => {
        setRubusd(Math.random() * 2);
      }, 10000);
      return () => clearInterval(interval);
    }, [])



    function changeSelect(event) {
        setValue(event.target.value)
    }
    const [modalBuyActive, setModalBuyActive] = useState(false)
    const [modalSellActive, setModalSellActive] = useState(false)



    return (
        <div>
        <select value = {value} onChange={changeSelect}>
        <option selected></option>
        <option name="USD/RUB" value={usdrub}>USD/RUB</option>
        <option name="RUB/USD" value={rubusd}>RUB/USD</option>
        </select>
        <div className="Curr">
          <div className="Buy" name="buy"> <button className="Buy" type="btn" onClick={() => setModalBuyActive(true)}>BUY {value + 1} </button>
          </div>
          <div className="Sell" name="sell"><button className="Sell" type="btn"  onClick={() => setModalSellActive(true)}>SELL {value}</button></div>
          </div>
          <Modalbuy active={modalBuyActive} setActive={setModalBuyActive} price={value + 1}/>
          <Modalsell active={modalSellActive} setActive={setModalSellActive} price={value}/>
        </div>
        
    )
}

export default Select

相关组件代码

Modalbuy.js

import React from "react";
import "./modal.css";

const Modalbuy = ({active, setActive,price}) => {
  
    return (
        <div className={active ? "modal active" : "modal"} onClick={() => setActive(false)}>
          <div className="modal__content" onClick={e => e.stopPropagation()}>
            <header>Make order</header>
            <p>BUY {price}</p>
            <input placeholder="Volume"></input>
            <div>
              <button>Ok</button>
              <button>Cancel</button>
            </div>

          </div>
        </div>
    )
}

export default Modalbuy;

Modalsell.js

import React from "react";
import "./modal.css";

const Modalsell = ({active, setActive,price}) => {
    return (
        <div className={active ? "modal active" : "modal"} onClick={() => setActive(false)}>
          <div className="modal__content" onClick={e => e.stopPropagation()}>
            <header>Make order</header>
            <p>SELL {price}</p>
            <input placeholder="Volume"></input>
            <div>
              <button>Ok</button>
              <button>Cancel</button>
            </div>

          </div>
        </div>
    )
}

export default Modalsell;

Timer.js

import React from 'react';
import {useState, useEffect} from 'react'


const Timer = () => {
  const [time, setTime] = useState(new Date().toLocaleTimeString());
  useEffect(() => {
    const interval = setInterval(() => {
      setTime(new Date().toLocaleTimeString());
    }, 1000);
    return () => clearInterval(interval);
  }, []);
  

  
    return (      
      <div className="clock">
        {time}      
      </div>
    );
  };


  export default Timer;

Trading.js

import React from "react";
import Timer from "./Timer";
import Select from "./select_curr/Select";

const Trading = () => {
    return (
        <div>
        <Timer/>
        <Select/>
        </div>
    )
}

export default Trading;

App.js

import './App.css';
import Page from './components/page/page'

function App() {
  return (
    <div className="App">
      <Page/>

    </div>
  );
}

export default App;

问题修复与优化方案

1. 汇率值同步问题修复

当前代码的核心问题:

  • Select的option值是组件初始化时的固定值,当usdrub/rubusd定时更新时,option的value不会同步,导致选中后拿到的是旧汇率
  • value存储的是字符串类型的汇率,value + 1会变成字符串拼接(比如"62+1"变成"621"),而非数值计算

修改后的Select组件:

import React, { useState, useEffect } from "react";
import './select.css'
import Modalbuy from "../popup/Modalbuy"
import Modalsell from "../popup/Modalsell"

const Select = () => {
    // 存储选中的货币对标识,而非直接存汇率值
    const [selectedPair, setSelectedPair] = useState("");
    const [usdrub, setUsdrub] = useState(Math.random() * (64-61) + 61);
    const [rubusd, setRubusd] = useState(Math.random() * 2);

    // 定时更新USD/RUB汇率
    useEffect(() => {
      const interval = setInterval(() => {
        setUsdrub(Math.random() * (64-61) + 61);
      }, 10000);
      return () => clearInterval(interval);
    }, [])

    // 定时更新RUB/USD汇率
    useEffect(() => {
      const interval = setInterval(() => {
        setRubusd(Math.random() * 2);
      }, 10000);
      return () => clearInterval(interval);
    }, [])

    // 获取当前选中货币对的实时汇率
    const getCurrentRate = () => {
        switch(selectedPair) {
            case "USD/RUB": return usdrub;
            case "RUB/USD": return rubusd;
            default: return 0;
        }
    }

    // 处理货币对选择变化
    function changeSelect(event) {
        setSelectedPair(event.target.value);
    }

    const [modalBuyActive, setModalBuyActive] = useState(false)
    const [modalSellActive, setModalSellActive] = useState(false)

    const currentRate = getCurrentRate();

    return (
        <div>
        <select value={selectedPair} onChange={changeSelect}>
        <option value="">请选择货币对</option>
        <option value="USD/RUB">USD/RUB</option>
        <option value="RUB/USD">RUB/USD</option>
        </select>
        <div className="Curr">
          <div className="Buy"> 
            <button className="Buy" onClick={() => setModalBuyActive(true)}>
              {/* 只在有选中值时显示价格,保留4位小数 */}
              BUY {currentRate > 0 ? (currentRate + 1).toFixed(4) : ""} 
            </button>
          </div>
          <div className="Sell">
            <button className="Sell" onClick={() => setModalSellActive(true)}>
              SELL {currentRate > 0 ? currentRate.toFixed(4) : ""}
            </button>
          </div>
          </div>
          {/* 传递实时汇率和货币对给Modal */}
          <Modalbuy active={modalBuyActive} setActive={setModalBuyActive} price={(currentRate + 1).toFixed(4)} pair={selectedPair}/>
          <Modalsell active={modalSellActive} setActive={setModalSellActive} price={currentRate.toFixed(4)} pair={selectedPair}/>
        </div>
    )
}

export default Select

2. Modal中使用Form组件的建议

如果需要收集交易量等订单信息并发送到其他标签页,强烈建议使用Form组件,可以更规范地处理表单验证和数据提交。以Modalbuy为例修改:

import React, { useState } from "react";
import "./modal.css";

const Modalbuy = ({active, setActive, price, pair}) => {
    const [volume, setVolume] = useState("");

    // 提交订单逻辑
    const handleSubmit = (e) => {
        e.preventDefault();
        // 验证交易量是否合法
        if (!volume || isNaN(volume) || parseFloat(volume) <= 0) return;
        
        // 构造订单数据
        const order = {
            type: "BUY",
            pair: pair,
            price: parseFloat(price),
            volume: parseFloat(volume),
            timestamp: new Date().toLocaleString()
        };
        console.log("提交订单:", order);
        // 这里可以通过props回调、全局状态或跨标签通信方式传递订单
        setActive(false);
        setVolume("");
    }

    return (
        <div className={active ? "modal active" : "modal"} onClick={() => setActive(false)}>
          <div className="modal__content" onClick={e => e.stopPropagation()}>
            <header>创建订单</header>
            <form onSubmit={handleSubmit}>
                <p>BUY {pair} @ {price}</p>
                <input 
                    type="number" 
                    placeholder="交易量" 
                    value={volume}
                    onChange={(e) => setVolume(e.target.value)}
                    min="0.01"
                    step="0.01"
                    required
                />
                <div>
                  <button type="submit">确认</button>
                  <button type="button" onClick={() => setActive(false)}>取消</button>
                </div>
            </form>
          </div>
        </div>
    )
}

export default Modalbuy;

3. 跨标签页传递订单信息的方案

如果需要将订单发送到其他标签页,可以选择以下几种方式:

  • LocalStorage/SessionStorage:提交订单时将数据存入storage,其他标签页监听storage事件获取新订单
  • Broadcast Channel API:专门用于同源标签页之间的消息通信
  • 全局状态管理:如果是单页应用的不同标签页组件,用React Context或Redux管理订单数据

以LocalStorage为例实现跨标签页通信:
在Modal的提交函数中添加:

const handleSubmit = (e) => {
    e.preventDefault();
    if (!volume || isNaN(volume) || parseFloat(volume) <= 0) return;
    
    const order = {
        type: "BUY",
        pair: pair,
        price: parseFloat(price),
        volume: parseFloat(volume),
        timestamp: new Date().toLocaleString()
    };
    // 将订单存入localStorage,触发其他标签页的storage事件
    localStorage.setItem("newOrder", JSON.stringify(order));
    setActive(false);
    setVolume("");
}

在接收订单的组件中添加监听:

import { useEffect, useState } from "react";

const OrderList = () => {
    const [orders, setOrders] = useState([]);

    useEffect(() => {
        const handleStorageChange = (e) => {
            if (e.key === "newOrder") {
                const newOrder = JSON.parse(e.newValue);
                setOrders(prev => [...prev, newOrder]);
            }
        }
        // 监听storage变化
        window.addEventListener("storage", handleStorageChange);
        // 组件卸载时移除监听
        return () => window.removeEventListener("storage", handleStorageChange);
    }, []);

    return (
        <div className="order-list">
            <h3>订单列表</h3>
            {orders.map((order, index) => (
                <div key={index} className="order-item">
                    <p>{order.type} {order.pair} | 价格:{order.price} | 交易量:{order.volume} | 时间:{order.timestamp}</p>
                </div>
            ))}
        </div>
    )
}

export default OrderList;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:45:45