如何使用 MongoDB 在 React 中动态创建按钮数组?

How to dynamically create an array of buttons in React using MonogoDB?

我正在尝试使用 MERN 堆栈将我的静态产品配置器转换为动态产品配置器,我真的快要完成测试版本了!我一切正常,但我无法让它变得更加动态。在我的配置器中 here for example, I have the ability to change colors through a list of hard coded buttons that trigger an event. This gets tedious with the amount of products that I will be trying to deploy to our website, and some products are only available in one, two, or three materials. I have successfully uploaded an array to MongoDB and is structured like so:

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

这是我对 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,但我不确定如何提取该信息并将其插入

这是我用来获取 ProductDetails 的 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,
    });
  }
};

如有任何帮助,我们将不胜感激!

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

  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>
  );
};

好的,在@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>
  );
};

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