【问题标题】:How to dynamically create an array of buttons in React using MonogoDB?如何使用 MongoDB 在 React 中动态创建按钮数组?
【发布时间】:2021-11-04 15:42:38
【问题描述】:

我正在尝试使用 MERN 堆栈将我的静态产品配置器转换为动态产品配置器,我真的很接近最终完成测试版本!我的一切正常,但我无法让它变得更有活力。例如,在我的配置器here 中,我能够通过触发事件的硬编码按钮列表来更改颜色。对于我将尝试部署到我们网站的产品数量,这变得乏味,有些产品只有一种、两种或三种材料可用。我已成功将一个数组上传到 MongoDB,其结构如下:

所以我的主要问题是,我将如何生成一个嵌套在手风琴内的按钮列表,就像我上面的示例一样,而手风琴的每个“部分”都将具有该材料选择的相关名称。

这是我的 HTML 硬编码片段以及我目前拥有的一些功能:

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 productDetails = useSelector((state) => state.getProductDetails);
  const {loading, error, product} = productDetails;

  useEffect(() => {
    if (product && match.params.id !== product._id) {
      dispatch(getProductDetails(match.params.id));
    }
    setCurrentSrc(product.src)
  }, [dispatch, match, product]);

  const changeColor = (event) => {
    const modelViewer = document.querySelector("model-viewer");
    modelViewer.variantName = event.target.value;
  };

  const [currentSrc, setCurrentSrc] = useState(product.src);

  return (*/HTML/*)
}
<div className="accordion">
  <div>
    <input type="radio" name="accordion" id="Lacquer" className="accordion__input" />
    <label htmlFor="Lacquer" className="materialLabel">Lacquer</label>
    <div className="items">
      <button onClick={changeColor} className='item' value='Ballet Pink'>Ballet Pink</button>
      <button onClick={changeColor} className='item' value="Bellini Peach">Bellini Peach</button>
      <button onClick={changeColor} className='item' value="Boeing Navy">Boeing Navy</button>
      <button onClick={changeColor} className='item' value="Cessna Grey">Cessna Grey</button>
      <button onClick={changeColor} className='item' value="Charter Coral">Charter Coral</button>
      <button onClick={changeColor} className='item' value="Cirrus White">Cirrus White</button>
      <button onClick={changeColor} className='item' value="Citation Blue">Citation Blue</button>
      <button onClick={changeColor} className='item' value="Dash Pink">Dash Pink</button>
      <button onClick={changeColor} className='item' value="Falcon Grey">Falcon Grey</button>
      <button onClick={changeColor} className='item' value="Gulfstream Blue">Gulfstream Blue</button>
      <button onClick={changeColor} className='item' value="Havilland Sage">Havilland Sage</button>
      <button onClick={changeColor} className='item' value="Illuminating Yellow">Illuminating Yellow</button>
      <button onClick={changeColor} className='item' value="Lear Green">Lear Green</button>
      <button onClick={changeColor} className='item' value="Merlin Lavender">Merlin Lavender</button>
      <button onClick={changeColor} className='item' value="Midnight Green">Midnight Green</button>
      <button onClick={changeColor} className='item' value="Polar Ice">Polar Ice</button>
      <button onClick={changeColor} className='item' value="Smoky Blue">Smoky Blue</button>
      <button onClick={changeColor} className='item' value="Stratos Black">Stratos Black</button>
      <button onClick={changeColor} className='item' value="Vitamin C">Vitamin C</button>
    </div>
  </div>
  <div>
    <input type="radio" name="accordion" id="Wood" className="accordion__input" />
    <label htmlFor="Wood" className="materialLabel">Wood</label>
    <div className="items">
      <button onClick={changeColor} className='item' value="Golden Pecan Mappa Burl">Golden Pecan Mappa Burl</button>
      <button onClick={changeColor} className='item' value="Golden Pecan Olive Ash">Golden Pecan Olive Ash</button>
      <button onClick={changeColor} className='item' value="Natural Mappa Burl">Natural Mappa Burl</button>
      <button onClick={changeColor} className='item' value="Natural Olive Ash">Natural Olive Ash</button>
      <button onClick={changeColor} className='item' value="Provincial Mappa Burl">Provincial Mappa Burl</button>
      <button onClick={changeColor} className='item' value="Provincial Olive Ash">Provincial Olive Ash</button>
    </div>
  </div>
</div>

现在我可以通过 console.log(product.material) 查看产品 JSON,但我不确定如何提取该信息并将其插入

这是我用来 getProductDetails 的 redux/axios 部分:

export const getProductDetails = (id) => async(dispatch) => {
  try {
    dispatch({type: actionTypes.GET_PRODUCT_DETAILS_REQUEST});
    
    const {data} = await axios.get(`/api/products/${id}`);
    
    dispatch({
      type: actionTypes.GET_PRODUCT_DETAILS_SUCCESS,
      payload: data,
    });
  } catch (error) {
    dispatch({type: actionTypes.GET_PRODUCT_DETAILS_FAIL,
      payload: error.response && error.response.data.message ?
        error.response.data.message :
        error.message,
    });
  }
};

任何帮助将不胜感激!

【问题讨论】:

  • 在获取数据数组后使用map方法...您获取的数据是哪个状态?
  • @Ebay 对不起,我的数据提取到哪个状态是什么意思?我对使用全栈工作流程相当陌生,所以我不确定。我使用useSelector((state) =&gt; state.getProductDetails getProductDetails 来自redux/axios 的一个名为actions 的文件夹中,我更新了关于如何使用redux/axios 执行此操作的问题。希望这能回答您的问题?

标签: javascript html reactjs mongodb mern


【解决方案1】:

为了简单起见,您应该创建一个自定义组件来表示您的输入单选和循环

  1. materials对象列表
  2. 里面的值列表

ProductScreen:

{
  product && product.materials[0].map((material) => (
    <CustomRadioButton material={material} changeColor={changeColor} />
  ));
}

创建一个新的CustomRadioButton 组件

export const CustomRadioButton = ({ material, changeColor }) => {
  const materialName = Object.keys(material);
  if (!materialName) return <></>;
  return (
    <div>
      <input
        type='radio'
        name='accordion'
        id={materialName}
        className='accordion__input'
      />
      <label htmlFor={materialName} className='materialLabel'>
        {materialName}
      </label>
      <div className='items'>
        {material[materialName].map((item) => (
          <button onClick={changeColor} className='item' value={item}>
            {item}
          </button>
        ))}
      </div>
    </div>
  );
};

【讨论】:

  • 太棒了,谢谢你的帮助!我很快就会在这里测试并报告!
  • 好吧,我已经玩了大约一个小时了,我不断收到"somehting".map is not a functionCannot convert undefined or null to object。知道是什么原因造成的吗?与此同时,我将继续玩它,看看我能弄清楚什么!再次感谢您为我指明正确的方向!
  • 在您的帮助下,我终于弄清楚了如何控制台记录我的材料,所以谢谢您。如果它对你有帮助,那就是console.log((product.materials)[0].Lacquer[0]),这将给我阵列中的第一个漆颜色。
  • @WadeMorrison 尝试更改已编辑答案中的代码。
  • 好的,我现在明白了!我将在下面发布对我有用的内容。而且我仍然会赞成您的回答,因为我相信它可以帮助其他人遇到不同的情况!非常感谢您的帮助,让我指出正确的方向!现在进入下一个问题!
【解决方案2】:

好的,在@LuccaPizzini 的帮助下,我能够弄清楚如何让它发挥作用! 这是我必须做的:

Product Screen:

{
  product && (product.materials ||).map((material, index) => (
    <CustomRadioButton key={index} material={material} changeColor={changeColor} />
  ))
}

新建一个CustomRadioButton组件:

export const CustomRadioButton = ({ material, changeColor }) => {
  const materialName = Object.keys(material);
  if (!materialName) return <></>;
  return (
    <div>
      <input
        type='radio'
        name='accordion'
        id={materialName}
        className='accordion__input'
      />
      <label htmlFor={materialName} className='materialLabel'>
        {materialName}
      </label>
      <div className='items'>
        {material[materialName].map((item) => (
          <button key={item} onClick={changeColor} className='item' value={item}>
            {item}
          </button>
        ))}
      </div>
    </div>
  );
};

基本上,这两个组件与他提供的内容相比变化非常小。

【讨论】:

    猜你喜欢
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多