反应中的干燥原理?

发布于 2025-01-17 14:31:14 字数 2819 浏览 0 评论 0原文

我正在学习反应,并试图将自己的最佳实践缠绕在我的脑海中,以创建多个用户,除了我的代码中的不同项目外,这些用户基本上做了同样的事情。

例如,我的代码是以下内容:

import { Button, Typography } from '@mui/material';
import { Box } from '@mui/system';
import React, {useState} from 'react';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';

export default MenuPage(){
  
   const menuItems = [
    {
        name: 'Americano',
        price: 1.50,
    },
    {
        name: 'Espresso',
        price: 3.50,
    },
    {
        name: 'Macchiato',
        price: 5.50,
    },
    {
        name: 'Cafe Mocha',
        price: 8.50,
    },
    {
        name: 'Latte',
        price: 6.50,
    },
    {
        name: 'Cappucino',
        price: 5.50,
    },
    {
        name: 'Frappe',
        price: 8.50,
    },
];

//*********************************************
// code that needs to be changed here instead of creaing n many useStates for n many items in menuItems list.

   const [order, setOrder] = useState('');

   const handleChange = (event) => {
    setOrder(event.target.value);
   };

//*********************************************

return(
     {menuItems.map((item) => {
            return (
                <Box display='flex' flexDirection='row' alignItems='center' justifyContent='center' textAlign='center' borderBottom='0.5px solid black' sx={{ my: 10, mx: 10 }}>
                    <Box flex={1} textAlign='center' sx={{ fontSize: '35px', }}>
                        {item.name}:
                    </Box>
                    <br />
                    <Box flex={1} textAlign='center' sx={{ fontSize: '25px' }}>
                        ${item.price}0
                    </Box>
                    <Box flex={0.5} textAlign='center'>
                        <FormControl fullWidth>
                            <InputLabel id="demo-simple-select-label">Order</InputLabel>
                            <Select
                                value={order}
                                label="Order"
                                onChange={handleChange}>
                                <MenuItem value={1}>1</MenuItem>
                                <MenuItem value={2}>2</MenuItem>
                                <MenuItem value={3}>3</MenuItem>
                            </Select>
                        </FormControl>
                    </Box>
                </Box>

            );
        })}

);
}

所以我的问题是,而不是创建许多const [nthorder,setnthorder] = usestate(''')是为每个顺序创建尽可能多的usestates的最佳方法?我知道我们不能在回调或浮桥中运行Usestate。

感谢您提前的帮助。

I am learning react and trying to wrap around my head on the best practices for creating multiple useStates that essentially do the same thing except for different items in my code.

For example, my code is the follow:

import { Button, Typography } from '@mui/material';
import { Box } from '@mui/system';
import React, {useState} from 'react';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';

export default MenuPage(){
  
   const menuItems = [
    {
        name: 'Americano',
        price: 1.50,
    },
    {
        name: 'Espresso',
        price: 3.50,
    },
    {
        name: 'Macchiato',
        price: 5.50,
    },
    {
        name: 'Cafe Mocha',
        price: 8.50,
    },
    {
        name: 'Latte',
        price: 6.50,
    },
    {
        name: 'Cappucino',
        price: 5.50,
    },
    {
        name: 'Frappe',
        price: 8.50,
    },
];

//*********************************************
// code that needs to be changed here instead of creaing n many useStates for n many items in menuItems list.

   const [order, setOrder] = useState('');

   const handleChange = (event) => {
    setOrder(event.target.value);
   };

//*********************************************

return(
     {menuItems.map((item) => {
            return (
                <Box display='flex' flexDirection='row' alignItems='center' justifyContent='center' textAlign='center' borderBottom='0.5px solid black' sx={{ my: 10, mx: 10 }}>
                    <Box flex={1} textAlign='center' sx={{ fontSize: '35px', }}>
                        {item.name}:
                    </Box>
                    <br />
                    <Box flex={1} textAlign='center' sx={{ fontSize: '25px' }}>
                        ${item.price}0
                    </Box>
                    <Box flex={0.5} textAlign='center'>
                        <FormControl fullWidth>
                            <InputLabel id="demo-simple-select-label">Order</InputLabel>
                            <Select
                                value={order}
                                label="Order"
                                onChange={handleChange}>
                                <MenuItem value={1}>1</MenuItem>
                                <MenuItem value={2}>2</MenuItem>
                                <MenuItem value={3}>3</MenuItem>
                            </Select>
                        </FormControl>
                    </Box>
                </Box>

            );
        })}

);
}

So my question is that instead of creating n many const [nthOrder, setNthOrder] = useState('') whats the best way to create as many useStates for each order ? I know we cannot run useState in a callBack or in forloops.

Thanks for your help in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

终弃我 2025-01-24 14:31:14

如果您想在同一状态下有几个订单,则可以将状态设置为数组,并将订单添加到数组中。

   const [order, setOrder] = useState(['']);

   const handleChange = (event) => {
    setOrder(prevState => { return [...prevState, event.target.value]});
   };

在此示例中,您可以看到我使用传播操作员返回具有先前值以及新值的新数组,这样您就可以避免重复。

If you want to have several orders in the same state, you can set the state as array and add the order to the array.

   const [order, setOrder] = useState(['']);

   const handleChange = (event) => {
    setOrder(prevState => { return [...prevState, event.target.value]});
   };

In this example you can see that i use the spread operator to return a new array with the previous values plus the new value, that way you can avoid the repetition.

双手揣兜 2025-01-24 14:31:14

我的解决方案是将menuitems作为组件状态。将订单字段添加到每个菜单项。将状态及其CRUD逻辑放入自定义挂钩中,保持组件清洁。

import React, { useState } from 'react';

function useMenuItems() {
  const [menuItems, setMenuItems] = useState([
    { name: 'Americano', price: 1.5, order: '' },
    { name: 'Espresso', price: 3.5, order: '' },
    { name: 'Macchiato', price: 5.5, order: '' },
    { name: 'Cafe Mocha', price: 8.5, order: '' },
    { name: 'Latte', price: 6.5, order: '' },
    { name: 'Cappucino', price: 5.5, order: '' },
    { name: 'Frappe', price: 8.5, order: '' },
  ]);

  const setOrderForMenuItem = (nOrder, itemName) => {
    setMenuItems((pre) => {
      return pre.map((v) => (v.name === itemName ? { ...v, order: nOrder } : v));
    });
  };

  return { menuItems, setOrderForMenuItem } as const;
}

export default function MenuPage() {
  const { menuItems, setOrderForMenuItem } = useMenuItems();

  const handleChange = (event, item) => {
    setOrderForMenuItem(event.target.value, item.name);
  };

  return (
    <div>
      {menuItems.map((item, i) => {
        return (
          <select
            data-testid={`menu-order-${i}`}
            key={item.name}
            value={item.order}
            onChange={(e) => handleChange(e, item)}
          >
            <option value={1}>1</option>
            <option value={2}>2</option>
            <option value={3}>3</option>
          </select>
        );
      })}
    </div>
  );
}

My solution is to maintain the menuItems as a state of the component. Add the order field to each menu item. Put the state and its CRUD logic into a custom hook, keep your component clean.

import React, { useState } from 'react';

function useMenuItems() {
  const [menuItems, setMenuItems] = useState([
    { name: 'Americano', price: 1.5, order: '' },
    { name: 'Espresso', price: 3.5, order: '' },
    { name: 'Macchiato', price: 5.5, order: '' },
    { name: 'Cafe Mocha', price: 8.5, order: '' },
    { name: 'Latte', price: 6.5, order: '' },
    { name: 'Cappucino', price: 5.5, order: '' },
    { name: 'Frappe', price: 8.5, order: '' },
  ]);

  const setOrderForMenuItem = (nOrder, itemName) => {
    setMenuItems((pre) => {
      return pre.map((v) => (v.name === itemName ? { ...v, order: nOrder } : v));
    });
  };

  return { menuItems, setOrderForMenuItem } as const;
}

export default function MenuPage() {
  const { menuItems, setOrderForMenuItem } = useMenuItems();

  const handleChange = (event, item) => {
    setOrderForMenuItem(event.target.value, item.name);
  };

  return (
    <div>
      {menuItems.map((item, i) => {
        return (
          <select
            data-testid={`menu-order-${i}`}
            key={item.name}
            value={item.order}
            onChange={(e) => handleChange(e, item)}
          >
            <option value={1}>1</option>
            <option value={2}>2</option>
            <option value={3}>3</option>
          </select>
        );
      })}
    </div>
  );
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文