如何在React中使用map创建独立的子元素

发布于 2025-01-17 06:55:39 字数 1551 浏览 2 评论 0原文

我可以成功地使用 map 从数组内部创建多个元素,但我正在创建的按钮以及分配给每个子元素的状态似乎与第一个映射相关联。此处的代码和屏幕截图。

import React, {useState} from 'react';
import './Switch.css'

const Switch = () => {
    const [status, setStatus] = useState(true);  
    
    const meats = [
        "Chicken", 
        "Ground Beef",
        "Sausage"
    ]

    const meatSwitches = meats.map((meat) =>
    
            <>
            <div id="ingredientContainer" className={status === true ? 'containerYes' : 'containerNo'}>
                
                    <h2 id='ingredientLabel'>{meat}</h2>
                    <div id="underLabel">
                        <h3 id='yes'>Sounds Yummy! </h3>
                        <input
                            className="react-switch-checkbox"
                            id={`react-switch-new`}
                            type="checkbox"
                            onClick={() => setStatus(!status)}
                            
                        />
                        <label
                            className="react-switch-label"
                            htmlFor={`react-switch-new`}
                        >
                            <span className={`react-switch-button`} />
                        </label>
                        <h3 id='no'>No, thanks.</h3>
                    </div>
                </div>
            </>
    );

如何让每个子元素都有一个功能按钮,独立于第一个元素并具有独立的状态(在本例中为“true”和“false”)。

I can successfully use map to create multiple elements from inside my array, but the button that I'm creating and the state I'm assigning to each child element seems to be tied back to the first mapping. Code here along with screen shot.

import React, {useState} from 'react';
import './Switch.css'

const Switch = () => {
    const [status, setStatus] = useState(true);  
    
    const meats = [
        "Chicken", 
        "Ground Beef",
        "Sausage"
    ]

    const meatSwitches = meats.map((meat) =>
    
            <>
            <div id="ingredientContainer" className={status === true ? 'containerYes' : 'containerNo'}>
                
                    <h2 id='ingredientLabel'>{meat}</h2>
                    <div id="underLabel">
                        <h3 id='yes'>Sounds Yummy! </h3>
                        <input
                            className="react-switch-checkbox"
                            id={`react-switch-new`}
                            type="checkbox"
                            onClick={() => setStatus(!status)}
                            
                        />
                        <label
                            className="react-switch-label"
                            htmlFor={`react-switch-new`}
                        >
                            <span className={`react-switch-button`} />
                        </label>
                        <h3 id='no'>No, thanks.</h3>
                    </div>
                </div>
            </>
    );

How can I get each child element to have a functioning button, individual of the first and with independent states (in this case of 'true' and 'false').

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

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

发布评论

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

评论(3

阪姬 2025-01-24 06:55:39

有两种常见的方法:

1。创建一个具有自己的单一 boolean 状态的 Meat 子组件
并将此状态保持在子级,独立于父组件 Switch。如果需要,您可以通过回调函数 onStatusChange(例如使用 useEffect())将 status 数据传递回父级。

  const Meat = ({ meat, onStatusChange } ) => {
    const [status, setStatus] = useState(true);
    
    useEffect(() => onStatusChange(status), [status])
    
    return (
    <div
      id="ingredientContainer"
      className={status === true ? 'containerYes' : 'containerNo'}
    >
      // ... your jsx code here
    </div>
  }

您的 Switch 组件将如下所示:

const Switch = () => {
    const meats = [
        "Chicken", 
        "Ground Beef",
        "Sausage"
    ]

    const [statusList, setStatusList] = useState([]);  
    const handleStatusChange = (status) => {
      // do what you want with the individual status,
      // perhaps push it in a status array?
      setStatusList((prev) => [...prev, status]);
    };

    const meatSwitches = meats.map((meat) => 
      <Meat key={meat} meat={meat} onStatusChange={handleStatusChange} />
    )

2.使用肉类类型数组而不是布尔状态来存储复选框值,然后在需要时将其转换为布尔值。使用这种方法,您不必创建新的 Meat 子组件。

const Switch = () => {
    const [status, setStatus] = useState([]);  
    
    const meats = [
        "Chicken", 
        "Ground Beef",
        "Sausage"
    ];
    
    const handleStatusChange = (event, meat) => {
      if (event.target.checked) {
        // push meat type to list
        // when box is checked
        setStatus(prev => [...prev, meat]);
      } else {
        // remove meat type from list
        // when box is unchecked
        setStatus(prev => return prev.filter(type => type !== meat));
      }
    };

    const meatSwitches = meats.map((meat) =>
      <div
        {/* id and key need to be unique */}
        id={`ingredientContainer-${meat}`}
        key={meat}
        {/* check if box is checked */}
        className={status.includes(meat) ? 'containerYes' : 'containerNo'}
      >
        // code
        <input
          type="checkbox"
          onClick={(event) => handleStatusChange(event, meat)}
        />
        // ...
      </div>
    )

如果这能回答您的问题,请告诉我。

There are 2 common approaches:

1. Create a Meat child component with its own single boolean state
and keep this state at the child level, independent of the parent component Switch. You can pass the status data back to parent if you want, via a callback function onStatusChange, for example with an useEffect().

  const Meat = ({ meat, onStatusChange } ) => {
    const [status, setStatus] = useState(true);
    
    useEffect(() => onStatusChange(status), [status])
    
    return (
    <div
      id="ingredientContainer"
      className={status === true ? 'containerYes' : 'containerNo'}
    >
      // ... your jsx code here
    </div>
  }

And your Switch component will look like this:

const Switch = () => {
    const meats = [
        "Chicken", 
        "Ground Beef",
        "Sausage"
    ]

    const [statusList, setStatusList] = useState([]);  
    const handleStatusChange = (status) => {
      // do what you want with the individual status,
      // perhaps push it in a status array?
      setStatusList((prev) => [...prev, status]);
    };

    const meatSwitches = meats.map((meat) => 
      <Meat key={meat} meat={meat} onStatusChange={handleStatusChange} />
    )

2. Use an array of meat types instead of a boolean state to store checkbox values, then convert it to boolean values later when needed. With this approach you don't have to create a new Meat child component.

const Switch = () => {
    const [status, setStatus] = useState([]);  
    
    const meats = [
        "Chicken", 
        "Ground Beef",
        "Sausage"
    ];
    
    const handleStatusChange = (event, meat) => {
      if (event.target.checked) {
        // push meat type to list
        // when box is checked
        setStatus(prev => [...prev, meat]);
      } else {
        // remove meat type from list
        // when box is unchecked
        setStatus(prev => return prev.filter(type => type !== meat));
      }
    };

    const meatSwitches = meats.map((meat) =>
      <div
        {/* id and key need to be unique */}
        id={`ingredientContainer-${meat}`}
        key={meat}
        {/* check if box is checked */}
        className={status.includes(meat) ? 'containerYes' : 'containerNo'}
      >
        // code
        <input
          type="checkbox"
          onClick={(event) => handleStatusChange(event, meat)}
        />
        // ...
      </div>
    )

Let me know if this answers your question.

该代码稍微扩展并在下面“回答”。谢谢@kvooak 的帮助。事实证明,隐藏在 CSS 中以支持无响应按钮的复选框(实际上只是一些 CSS,没有“输入”功能)正是我所需要的。我使该复选框可见,添加到函数中以根据检查状态向数组添加或删除项目,并在末尾实时打印该数组,以证明应用程序正在保存/转储数组 allIngredients 中的正确项目。

import React, {useState} from 'react';
import './Switch.css'


const Switch = () => {
    const [status, setStatus] = useState([]); 
    const [checked, setChecked] = useState([]); 
    
    let meats = [
        "Chicken", 
        "Ground Beef",
        "Sausage",
        "Pork Chops"
    ];

    let starches = [
        "White Rice", "Bread", "Pasta",
        "Chips", "Idaho Potatoes", "Sweet Potatoes",
        "Tortillas", "Brown Rice", "Red Potatoes"
    ];

    const vegatables = [
        "Broccoli", "Green Beans", "Squash",
        "Corn", "Okra", "Carrots",
        "Onions", "Okra", "Zucchini"
    ]

    const spices = [
        "Cayenne Pepper", "Cumin", "Garlic Powder", 
        "Onion Powder", "Tumeric", "Garam Masala",
        "Chili Powder", "Crushed Red Pepper", "Oregano"
    ]

    let allIngredients = [...checked];

    const handleStatusChange = (event, ingredient) => {
        if (event.target.checked) {
          setStatus(prev => [...prev, ingredient]);
          allIngredients = [...checked, event.target.value];
        } else {
          setStatus(prev => prev.filter(type => type !== ingredient));
          allIngredients.splice(checked.indexOf(event.target.value), 1);
        }
        setChecked(allIngredients);
      };

      var checkedItems = checked.length
        ? checked.reduce((total, item) => {
            return total + ", " + item;
        })
        : "";

    const meatSwitches = meats.map((meat) =>
    
            <>
            <div id="ingredientContainer"  className={status.includes(meat) ? 'containerYes' : 'containerNo'}>
                
                    <p key={meat} id='ingredientLabel'>{meat}</p>
                    
                    <div id="underLabel">
                        <input
                            className="react-switch-checkbox"
                            value = {meat}
                            id={`react-switch-new`}
                            type="checkbox"
                            onClick={(event) => handleStatusChange(event, meat)}
                            
                        />
                        
                    </div>
                </div>
            </>
    );

    const starchSwitches = starches.map((starch) =>
    
    <>
    <div id="ingredientContainer"  className={status.includes(starch) ? 'containerYes' : 'containerNo'}>
        
            <p key={starch} id='ingredientLabel'>{starch}</p>
            
            <div id="underLabel">
                <input
                    className="react-switch-checkbox"
                    value={starch}
                    id={`react-switch-new`}
                    type="checkbox"
                    onClick={(event) => handleStatusChange(event, starch)}
                    
                />
                
            </div>
        </div>
    </>
);

const vegatableSwitches = vegatables.map((vegatable) =>
    
<>
<div id="ingredientContainer"  className={status.includes(vegatable) ? 'containerYes' : 'containerNo'}>
    
        <p key={vegatable} id='ingredientLabel'>{vegatable}</p>
        
        <div id="underLabel">
            <input
                className="react-switch-checkbox"
                value={vegatable}
                id={`react-switch-new`}
                type="checkbox"
                onClick={(event) => handleStatusChange(event, vegatable)}
                
            />
            
        </div>
    </div>
</>
);

const spiceSwitches = spices.map((spice) =>
    
<>
<div id="ingredientContainer"  className={status.includes(spice) ? 'containerYes' : 'containerNo'}>
    
        <p key={spice} id='ingredientLabel'>{spice}</p>
        
        <div id="underLabel">
            <input
                className="react-switch-checkbox"
                value={spice}
                id={`react-switch-new`}
                type="checkbox"
                onClick={(event) => handleStatusChange(event, spice)}
                
            />
            
        </div>
    </div>
</>
);

    return (
    <>
        {meatSwitches}
        {starchSwitches}
        {vegatableSwitches}
        {spiceSwitches}
        {checkedItems}
    </>
  );
};

export default Switch;

The code is expanded upon slightly and 'answered' below. Thank you @kvooak for your help. Turns out that the checkbox that was hidden in CSS in favor of an unresponsive button (literally just some CSS and no 'input' functionality) was what I needed. I made that checkbox visible, added in a function to add or remove items based on checked status to and from an array, and printed that array at the end in realtime to prove that the app was holding/dumping the right items from array allIngredients.

import React, {useState} from 'react';
import './Switch.css'


const Switch = () => {
    const [status, setStatus] = useState([]); 
    const [checked, setChecked] = useState([]); 
    
    let meats = [
        "Chicken", 
        "Ground Beef",
        "Sausage",
        "Pork Chops"
    ];

    let starches = [
        "White Rice", "Bread", "Pasta",
        "Chips", "Idaho Potatoes", "Sweet Potatoes",
        "Tortillas", "Brown Rice", "Red Potatoes"
    ];

    const vegatables = [
        "Broccoli", "Green Beans", "Squash",
        "Corn", "Okra", "Carrots",
        "Onions", "Okra", "Zucchini"
    ]

    const spices = [
        "Cayenne Pepper", "Cumin", "Garlic Powder", 
        "Onion Powder", "Tumeric", "Garam Masala",
        "Chili Powder", "Crushed Red Pepper", "Oregano"
    ]

    let allIngredients = [...checked];

    const handleStatusChange = (event, ingredient) => {
        if (event.target.checked) {
          setStatus(prev => [...prev, ingredient]);
          allIngredients = [...checked, event.target.value];
        } else {
          setStatus(prev => prev.filter(type => type !== ingredient));
          allIngredients.splice(checked.indexOf(event.target.value), 1);
        }
        setChecked(allIngredients);
      };

      var checkedItems = checked.length
        ? checked.reduce((total, item) => {
            return total + ", " + item;
        })
        : "";

    const meatSwitches = meats.map((meat) =>
    
            <>
            <div id="ingredientContainer"  className={status.includes(meat) ? 'containerYes' : 'containerNo'}>
                
                    <p key={meat} id='ingredientLabel'>{meat}</p>
                    
                    <div id="underLabel">
                        <input
                            className="react-switch-checkbox"
                            value = {meat}
                            id={`react-switch-new`}
                            type="checkbox"
                            onClick={(event) => handleStatusChange(event, meat)}
                            
                        />
                        
                    </div>
                </div>
            </>
    );

    const starchSwitches = starches.map((starch) =>
    
    <>
    <div id="ingredientContainer"  className={status.includes(starch) ? 'containerYes' : 'containerNo'}>
        
            <p key={starch} id='ingredientLabel'>{starch}</p>
            
            <div id="underLabel">
                <input
                    className="react-switch-checkbox"
                    value={starch}
                    id={`react-switch-new`}
                    type="checkbox"
                    onClick={(event) => handleStatusChange(event, starch)}
                    
                />
                
            </div>
        </div>
    </>
);

const vegatableSwitches = vegatables.map((vegatable) =>
    
<>
<div id="ingredientContainer"  className={status.includes(vegatable) ? 'containerYes' : 'containerNo'}>
    
        <p key={vegatable} id='ingredientLabel'>{vegatable}</p>
        
        <div id="underLabel">
            <input
                className="react-switch-checkbox"
                value={vegatable}
                id={`react-switch-new`}
                type="checkbox"
                onClick={(event) => handleStatusChange(event, vegatable)}
                
            />
            
        </div>
    </div>
</>
);

const spiceSwitches = spices.map((spice) =>
    
<>
<div id="ingredientContainer"  className={status.includes(spice) ? 'containerYes' : 'containerNo'}>
    
        <p key={spice} id='ingredientLabel'>{spice}</p>
        
        <div id="underLabel">
            <input
                className="react-switch-checkbox"
                value={spice}
                id={`react-switch-new`}
                type="checkbox"
                onClick={(event) => handleStatusChange(event, spice)}
                
            />
            
        </div>
    </div>
</>
);

    return (
    <>
        {meatSwitches}
        {starchSwitches}
        {vegatableSwitches}
        {spiceSwitches}
        {checkedItems}
    </>
  );
};

export default Switch;
执笏见 2025-01-24 06:55:39

您可以将状态设置为布尔数组,并使每个按钮对应于索引。例子:

const status, setStatus = useState([true, true, true])
const handleChange = (index) => {
  const prev = [...status];
  prev[index] = !prev[index];
  setStatus(prev);
  
}
const meatSwitches = meats.map((meat,index) =>

        <>
        <div id="ingredientContainer" className={status === true ? 'containerYes' : 'containerNo'}>
            
                <h2 id='ingredientLabel'>{meat}</h2>
                <div id="underLabel">
                    <h3 id='yes'>Sounds Yummy! </h3>
                    <input
                        className="react-switch-checkbox"
                        id={`react-switch-new`}
                        type="checkbox"
                        onClick={() => handleChange(index)}
                        
                    />
                    <label
                        className="react-switch-label"
                        htmlFor={`react-switch-new`}
                    >
                        <span className={`react-switch-button`} />
                    </label>
                    <h3 id='no'>No, thanks.</h3>
                </div>
            </div>
        </>
);

You can set the state to be an array of booleans, and have each button correspond to the index. Example:

const status, setStatus = useState([true, true, true])
const handleChange = (index) => {
  const prev = [...status];
  prev[index] = !prev[index];
  setStatus(prev);
  
}
const meatSwitches = meats.map((meat,index) =>

        <>
        <div id="ingredientContainer" className={status === true ? 'containerYes' : 'containerNo'}>
            
                <h2 id='ingredientLabel'>{meat}</h2>
                <div id="underLabel">
                    <h3 id='yes'>Sounds Yummy! </h3>
                    <input
                        className="react-switch-checkbox"
                        id={`react-switch-new`}
                        type="checkbox"
                        onClick={() => handleChange(index)}
                        
                    />
                    <label
                        className="react-switch-label"
                        htmlFor={`react-switch-new`}
                    >
                        <span className={`react-switch-button`} />
                    </label>
                    <h3 id='no'>No, thanks.</h3>
                </div>
            </div>
        </>
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文