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

MERN栈React项目如何用useState实现model-viewer 3D模型点击切换

方案说明

完全可以通过useState实现该需求,你当前代码的问题主要出在useEffect执行顺序错误、多余的srcOptions状态定义、按钮渲染逻辑错误三个点,以下是完整修正方案:


1. 修正后组件完整代码

import {useEffect, useState} from "react";
import {useSelector, useDispatch} from "react-redux";

// Actions
import {getProductDetails} from "../redux/actions/productActions";

const ProductScreen = ({match}) => {
    const dispatch = useDispatch();
    // 仅保留当前模型地址状态即可
    const [currentSrc, setCurrentSrc] = useState("");

    const productDetails = useSelector((state) => state.getProductDetails);
    const {loading, error, product} = productDetails;

    // 第一个effect:监听商品ID变化,拉取对应商品详情
    useEffect(() => {
        if (match.params.id !== product?._id) {
            dispatch(getProductDetails(match.params.id));
        }
    }, [dispatch, match.params.id, product?._id]);

    // 第二个effect:商品详情加载完成后,初始化默认显示的模型地址
    useEffect(() => {
        if (product) {
            setCurrentSrc(product.src);
        }
    }, [product]);

    return (
        <div className="productcreen">
            {loading ? (
                <h2>加载中...</h2>
            ) : error ? (
                <h2>{error}</h2>
            ) : (
                <>
                    <div className='sizebuttons'>
                        {/* 直接遍历三个模型配置生成按钮,无需多余的map逻辑 */}
                        {[
                            {src: product.src, size: product.size},
                            {src: product.src2, size: product.size2},
                            {src: product.src3, size: product.size3}
                        ].map((item, index) => (
                            <button key={index} onClick={() => setCurrentSrc(item.src)}>
                                {item.size}
                            </button>
                        ))}
                    </div>
                    <div className="productscreen__right">
                        <model-viewer 
                            id="model-viewer" 
                            src={currentSrc} 
                            alt={product.name} 
                            ar 
                            ar-modes="scene-viewer quick-look" 
                            ar-placement="floor" 
                            shadow-intensity="1" 
                            camera-controls 
                            min-camera-orbit={product.mincameraorbit} 
                            max-camera-orbit={product.maxcameraorbit} 
                            interaction-prompt="none"
                        >
                            <button slot="ar-button" className="ar-button">
                                在你的空间中查看
                            </button>
                        </model-viewer>
                    </div>
                </>
            )}
        </div>
    )
};

2. 改动说明

  • 移除了不必要的srcOptions状态:因为你的模型地址和对应尺寸是单独存储在MongoDB的三个独立字段中,不需要额外维护数组状态,直接通过临时配置数组遍历生成按钮即可
  • 拆分了useEffect逻辑:避免了请求未完成就给状态赋值旧数据的问题,保证状态更新时机准确
  • 修正了按钮渲染逻辑:点击按钮时直接将对应模型地址赋值给currentSrc,状态更新后会触发组件重渲染,model-viewer的src属性会自动更新,自动加载新的3D模型

3. 依赖补充

如果还未引入model-viewer依赖,需要在项目public/index.html的head标签中加入引入代码即可:

<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>

你原本编写的Redux请求逻辑不需要做任何修改,只要确保MongoDB中存储的src/src2/src3字段为正确的模型文件地址即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:54:03