【问题标题】:How to select and save my components ids in an array?如何选择我的组件 ID 并将其保存在数组中?
【发布时间】:2021-09-24 13:23:32
【问题描述】:

我有一个登录页面,其中包含一个传递给我的 TemplateList 组件的数组。而我的 TemplateList 组件是由 TemplateCard 组件组成的。

我的 TemplateList 上的每张卡片都可以选择,如果选择了超过 2 个卡片,页面上的按钮会激活 onOnboardingComplete,然后继续到下一页。

我想做的是能够获取我在页面上选择的每张卡片的唯一 ID 一旦我选择了一个或多个,将这些 ID 转换为我可以传递给的数组(称为:selectedTemplatesIds) onOnboardingComplete(按钮)。

使用 id 作为标识符,并以此为基础,我们得到一组选定的卡片,并通过 onOnboardingComplete 传递它。

我听说我可以使用 Object.keys,但以前从未这样做过。我该怎么做?

总结:

1.我希望能够在选中时获取我的卡唯一 ID,并在未选中时忽略它们

2。一旦我选择了一个或多个,将这些 id 转换为一个数组(selectedTemplatesIds),以便将它们传递给 onOnboardingComplete(TemplateList 中的按钮)。

这是我在 LandingPage 中使用的数组

    templates = [
        {
            title: "Grocery List",
            description: "Description of what this things does so the reader can have info of",
            imgURL: "https://res.cloudinary.com/deruwllkv/image/upload/v1625753993/groceries.png",
            id: 0,
        },

        {
            title: "Shopping Space",
            description: "blablabalblabla",
            imgURL: "https://res.cloudinary.com/deruwllkv/image/upload/v1625753766/shopping.png",
            id: 1,
        },

        {
            title: "Travel Planning",
            description: "blablabalblabla",
            imgURL: "https://res.cloudinary.com/deruwllkv/image/upload/v1625753885/travel.png",
            id: 2,
        },

        {
            title: "Travel",
            description: "blablabalblabla",
            imgURL: "https://res.cloudinary.com/deruwllkv/image/upload/v1625753993/groceries.png",
            id: 3,
        },
    ];

我的模板列表组件:

export type Template = {
    title: string;
    description: string;
    imgURL: string;
    id?: number;
};

type Props = {
    templates: Template[];
    onOnboardingComplete: Function;
};

const TemplateList = ({ templates, onOnboardingComplete }: Props) => {
    const { aspectRatio, vmin } = useWindowResponsiveValues();

    const [noOfSelectedCards, setNoOfSelectedCards] = useState(0);

    const handleSelect = () => setNoOfSelectedCards(noOfSelectedCards + 1);
    const handleDeselect = () => setNoOfSelectedCards(noOfSelectedCards - 1);

    let buttonText;
    if (noOfSelectedCards === 1) {
        buttonText = "Select at least 1 more option";
    } else if (noOfSelectedCards >= 2) {
        buttonText = "Create my initial cuadds!";
    } else {
        buttonText = "Select at least 2 options";
    }

    return (
        <>
            <div className={styles.scrollContainer}>
                {templates.map((item) => (
                    <TemplateCard
                        title={item.title}
                        description={item.description}
                        img={item.imgURL}
                        classNameToAdd={styles.cardContainer}
                        key={item.id}
                        onSelectCard={handleSelect}
                        onDeselectCard={handleDeselect}
                    />
                ))}
            </div>
            <MenuButton
                onClick={onOnboardingComplete}
                style={actionButton}
                className={
                    noOfSelectedCards >= 2 ? `${styles.actionBlue}` : `${styles.actionNormal}`
                }
            >
                {buttonText}
            </MenuButton>
        </>
    );
};

export default TemplateList;

还有我的模板卡片:

type Props = {
    title: string;
    description: string;
    img: string;
    classNameToAdd?: string;
    classNameOnSelected?: string;
    onSelectCard: any;
    onDeselectCard: any;
};

const TemplateCard = ({
    title,
    description,
    img,
    classNameToAdd,
    classNameOnSelected,
    onSelectCard,
    onDeselectCard,
}: Props) => {
    const { aspectRatio, vmin } = useWindowResponsiveValues();
    let className = `${styles.card} ${classNameToAdd}`;

    const [selected, setSelected] = useState(false);

    const handleClick = () => {
        setSelected(!selected);
        if (selected) {
            onDeselectCard();
        } else {
            onSelectCard();
        }
    };

    if (selected) {
        className += `${styles.card} ${classNameToAdd} ${classNameOnSelected}`;
    }



    return (
        <div style={card} className={className} onClick={handleClick}>
            <img style={imageSize} src={img}></img>
            <div style={cardTitle}>
                {title}
                {selected ? <BlueCheckIcon style={blueCheck} className={styles.blueCheck} /> : null}
            </div>
            <div style={descriptionCard}>{description}</div>
        </div>
    );
};

TemplateCard.defaultProps = {
    classNameOnSelected: styles.selected,
};

export default TemplateCard;

【问题讨论】:

    标签: javascript arrays reactjs sorting react-hooks


    【解决方案1】:

    而不仅仅是存储 noOfSelectedCards。只需存储 id 数组即可:

    const [selectedIds, setSelectedIds] = useState([]);
    

    将 id 发送到 handleSelect 函数中,并将 id 推送到数组中。

    <TemplateCard
        title={item.title}
        description={item.description}
        img={item.imgURL}
        classNameToAdd={styles.cardContainer}
        key={item.id}
        onSelectCard={() => handleSelect(item.id)}
        onDeselectCard={handleDeselect}
    />
    
    handleSelect(id) {
        setSelectedIds(prev => [...prev, id])
    }
    

    您可以在取消选择卡片时执行类似的操作来删除 id。

    【讨论】:

    • 将 selectedIds 作为钩子会导致额外的重新渲染,因为 handleSelect 函数已经通过 setNoOfSelectedCards 更新了状态;在用户完成表单之前,所选的 id 本身是无关紧要的,因此不需要使用状态。此外,onSelectCard={handleSelect(item.id)} 会在渲染时调用该函数来创建无限重新渲染。
    【解决方案2】:

    添加:

    const selectedTemplatesIds = [];

    更改处理程序:

    const handleSelect = (id) => {
      selectedTemplatesIds.push(id);
      setNoOfSelectedCards(noOfSelectedCards + 1);
    };
    const handleDeselect = (id) => {
      selectedTemplatesIds.splice(selectedTemplatesIds.indexOf(id),1);
      setNoOfSelectedCards(noOfSelectedCards - 1);
      
    }
    

    变化:

    <TemplateCard
                        title={item.title}
                        description={item.description}
                        img={item.imgURL}
                        classNameToAdd={styles.cardContainer}
                        key={item.id}
                        onSelectCard={() => {
                                            handleSelect(item.id)
                                      }}
                        onDeselectCard={() => {
                                            handleDeselect(item.id)
                                      }}
                    />
    

    【讨论】:

    • 完美!这样做是有意义的。所以我通过handleSelect将ids传递给数组,并删除了我通过handleDeselect取消选择的ids。不过,在这样做之后,如何将我的数组传递给我的按钮并通过我的 TemplatesList 中的道具 onOnboardingComplete (onClick={onOnboardingComplete})?
    • 这是我的 onOnboardingComplete 函数: const onOnboardingComplete = (selectedTemplatesIds) => { console.log("selectedTemplatesIds", selectedTemplatesIds); if (user.training?.level { navigate("/"); }); } else { 导航(“/”); } };
    • 当您设置按钮的 onClick 处理程序时,您将函数传递给它但没有调用它,这是正确的方法。但是,如果您需要在调用时将参数传递给该函数,则使用箭头函数作为处理程序,因此 onClick={onOnboardingComplete} 变为 onClick={() =&gt;{ onOnboardingComplete(selectedTemplatesIds); }}
    猜你喜欢
    • 2015-10-17
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 2022-11-14
    • 2019-07-05
    相关资源
    最近更新 更多