如何将字符串插入数组的次数与输入的 int 值相同?

How to insert a string into an array the same amount of times as the int value from an input?

我有这个猫鼬模式

const storeSchema = mongoose.Schema({
    name: {
        type: String,
        required: true,
    },
    fruits: {
        type: [String],
        required: true,
    },
});

在我的客户端,我正在为名称输入执行此操作,到目前为止它正在运行。

const [store, setStoreData] = useState({
    store: '',
    fruits: [''],
});

const dispatch = useDispatch();

const handleSubmit = (e) => {
    e.preventDefault();
    dispatch(addStore(store));
};

...


<TextField
    label='Store Name'
    variant='outlined'
    value={store.name}
    onChange={(e) =>
         setStoreData({
             ...store,
             name: e.target.value,
         })
    }
/>

我试图模仿这种行为,但我认为它必须更复杂。问题是我想为每个水果设置 2 或 3 个这样的“输入 select”。每个都有多个 int 选择,如 1、2、3。并根据目标值,将水果数量推入 fruits 数组。这就是我的。

<Select
    value={store.fruits}
    label='Fruits'
    onChange={(e) =>
        setStoreData({
            ...store,
            fruits: e.target.value,
        })
    }>
    <MenuItem value={1}>1</MenuItem>
    <MenuItem value={2}>2</MenuItem>
    <MenuItem value={3}>3</MenuItem>
</Select>

所以理想情况下,我会有 3 个这样的输入,一个用于每种水果,如香蕉和苹果,并且客户选择的数字将是香蕉将插入到数组中的条目数。

示例:select 表示我有 3 个(数字 3)香蕉。 我会在数据库中得到这个。

{
    "name": store
    "fruits": ["banana", "banana", "banana"] 
}

我正在使用@mui/material 进行反应。

一个好的解决方案可能是将您的状态结构更改为输入更友好的结构,然后在提交时将此值转换为与您的商店架构匹配的结构。

您的州声明可能看起来像这样;

const [store, setStoreData] = useState({
   name: "",
   fruits: {
      apple: 0,
      banana: 0,
      orange: 0
  },
});

然后您可以使用共享方法来更新您所在州的水果值。

const handleChangeFruit = (name, value) => {
        setStoreData(store => ({
            ...store,
            fruits: {
                ...store.fruits,
                [name]: value
            }
        }));
    }

然后你的水果Select输入变成:

<Select
    value={store.fruits.apple}
    label='apple'
    onChange={(e) =>
        handleChangeFruit('apple', parseInt(e.target.value))
    }>
    <MenuItem value={1}>1</MenuItem>
    <MenuItem value={2}>2</MenuItem>
    <MenuItem value={3}>3</MenuItem>
</Select>

要将此状态转换为您的模式形状,您可以执行如下操作;

const getStoreData = () => {
  const fruits = Object.entries(store.fruits).reduce(
    (acc, cur) => acc.concat(new Array(cur[1]).fill(cur[0])),
    []
  );
  return {
    name: store.name,
    fruits,
  };
};

您的 handleSubmit 方法现在变为:

const handleSubmit = (e) => {
  e.preventDefault();
  dispatch(addStore(getStoreData()));
};

这应该可以解决问题。

为了获得额外的智能点,您甚至可以像这样动态生成 Select 字段:

Object.keys(store.fruits).map((fruit) => (
  <Select
    key={fruit}
    value={store.fruits[fruit]}
    label={fruit}
    onChange={(e) => handleChangeFruit(fruit, parseInt(e.target.value))}
  >
    <MenuItem value={1}>1</MenuItem>
    <MenuItem value={2}>2</MenuItem>
    <MenuItem value={3}>3</MenuItem>
  </Select>
));