ReactJs:如何将数据从一个组件传递到另一个组件?

ReactJs: How to pass data from one component to another?

如果组件中的两张或更多卡片被 selected 如何将数据传递给按钮组件?

我有一个包含两个组件的登录页面;模板列表和一个按钮。

<TemplateList templates={templates} />

                <MenuButton style={actionButton} onClick={onOnboardingComplete}>
                    Select at least 2 options
                </MenuButton>

TemplateList 为我的模板带来了一系列信息,并用它创建了模板卡。然后我可以 select 我的卡片并取消 select 它们。

我的按钮在按下时会带我进入入职的下一步。

我想知道我应该如何连接这两个组件。我的按钮现在是灰色的,希望发生这种情况:

1.按钮是灰色的,用户无法继续下一步,直到 select 两张或更多卡片。

2。当两张或更多卡片被 selected 时,按钮变为蓝色,他们可以按下按钮继续。

这是我的模板列表:

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

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

const TemplateList = ({ templates }: Props) => {
    return (
        <div className={styles.scrollContainer}>
            {templates.map((item) => (
                <TemplateCard
                    title={item.title}
                    description={item.description}
                    img={item.imgURL}
                    classNameToAdd={styles.cardContainer}
                    key={item.id}
                />
            ))}
        </div>
    );
};

export default TemplateList;

这是我的模板卡:



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

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

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

    const handleClick = () => {
        setSelected(!selected);
    };

    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;

这是现在的样子。

至少有 3 种方法可以实现您的要求:

选项 1

  1. 将 Button 组件放入 <TemplateList> 组件

  2. 添加一个 useState 绑定到 <TemplateList> 组件以保存数量 已选择的卡片

  3. 添加两个新道具 onSelectCardonDeselectCard<TemplateCard> 到 increment/decrement 由 1 为每个 selected/deselected 项

  4. <TemplateList 组件内实现回调函数(代码如下)

  5. 需要时在<TemplateCard>中调用onSelectCard(代码如下)

模板列表组件

const TemplateList = ({ templates }: Props) => {
  const [noOfSelectedCards, setNoOfSelectedCards] = useState(0);

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

  return (
    <div classNae="template-list-container">
      <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 style={actionButton} onClick={onOnboardingComplete} className={noOfSelectedCards === 2 ? 'active' : ''}>
        Select at least 2 options
      </MenuButton>
    </div>
  );
};

TemplateCard组件

const TemplateCard = ({ ..., onSelectCard, onDeselectCard }: Props) => {
  ...

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

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

  ...
};

现在,您将在您的状态 noOfSelectedCards<TemplateList> 组件)中拥有当前所选卡片的数量,因此您可以有条件地呈现任何 className 您想要的按钮或用它做点别的事。

选项 2

使用React Context在组件之间共享状态

在这种情况下使用 React Context 是可以的,但是如果您的要求包含应用程序中组件之间 handling/sharing 状态的其他类似情况,我建议您看一下第三个选项。

选项 3

使用 Redux 之类的状态管理来处理组件之间的 global/shared 状态。

对于跨应用程序共享状态非常普遍且重要的项目,这可能是最佳选择。您需要一些时间来了解有关 Redux 的概念,但在您了解之后,我向您保证您会喜欢使用它。