获取所选Card元素的ID,并将其传递给模式以选择元素

问题描述

我有一个代码,可以在Cards中呈现多个计划。这是代码:

import React,{ useEffect,useState } from 'react';
import { I18nText,Card,BaseModal,Button } from '@wtag/react-comp-lib';
import PropTypes from 'prop-types';
import greenCheck from 'affiliateIcons/green-check.svg';
import doneMark from '../../../../assets/images/done-24px.svg';
import routes from '../../../shared/routes';
import httpClient from '../../../shared/libraries/httpClient';

const Plans = ({ affiliateId }) => {
  const [plans,setPlans] = useState([]);
  const [currentPlan,setCurrentPlan] = useState([]);
  const [modalOpen,setModalOpen] = useState(false);

  const fetchPlans = async () => {
    const { data } = await httpClient.get(
      routes.billing.changePlan.fetch({ affiliate_id: affiliateId }),);
    setPlans(data.plans);
    setCurrentPlan(data.currentPlan);
  };

  const selectPlan = async plan => {
    const { data } = await httpClient.put(
      routes.billing.changePlan.update({
        id: plan.id,affiliate_id: affiliateId,}),);

    if (data.error === null) {
      fetchPlans(data.currentPlan);
      setModalOpen(false);
    }
  };

  useEffect(() => {
    fetchPlans();
  },[]);

  const data = [
    {
      id: 0,identifier: 'free-2020',name: <I18nText id="pricing.plans.name.free" />,planTitle: 'free',price: '00',freeSearches: <I18nText id="pricing.plans.features.unlimited" />,freeBookings: <I18nText id="pricing.plans.features.unlimited" />,travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,supportTickets: <I18nText id="pricing.plans.features.available" />,supportByPhone: '-',supplierChannels: '-',customDomain: '-',active: true,},{
      id: 1,identifier: 'basic-2020',name: <I18nText id="pricing.plans.name.basic" />,planTitle: 'basic',price: '29',supplierChannels: '1',active: false,{
      id: 2,identifier: 'standard-2020',name: <I18nText id="pricing.plans.name.standard" />,planTitle: 'standard',price: '59',supportByPhone: '1hr/mo',supplierChannels: '2',{
      id: 3,identifier: 'professional-2020',name: <I18nText id="pricing.plans.name.professional" />,planTitle: 'professional',price: '99',supportByPhone: '3hr/mo',supplierChannels: '5',customDomain: 'Yes',{
      id: 4,identifier: 'custom-2020',name: <I18nText id="pricing.plans.name.custom" />,planTitle: 'custom',price: '-',supportByPhone: <I18nText id="pricing.plans.features.unlimited" />,supplierChannels: <I18nText id="pricing.plans.features.unlimited" />,customDomain: <I18nText id="pricing.plans.features.available" />,];

  const planData = data.map(d => {
    const correspondingPlan = plans.filter(
      plan => d.identifier === plan.identifier,)[0];
    if (correspondingPlan) {
      return { ...d,...correspondingPlan };
    }
    return d;
  });

  const tableHeader = [
    { id: 0,name: <I18nText id="pricing.table.header.free" /> },{ id: 1,name: <I18nText id="pricing.table.header.basic" /> },{ id: 2,name: <I18nText id="pricing.table.header.standard" /> },{ id: 3,name: <I18nText id="pricing.table.header.professional" /> },{ id: 4,name: <I18nText id="pricing.table.header.custom" /> },];

  const planOptions = [
    {
      id: 0,name: <I18nText id="pricing.table.feature.subscription.search" />,isFree: doneMark,isBasic: doneMark,isStandard: doneMark,isProfessional: doneMark,isCustom: doneMark,name: <I18nText id="pricing.table.feature.subscription.bookings" />,name: <I18nText id="pricing.table.feature.subscription.traveler" />,name: <I18nText id="pricing.table.feature.subscription.corporate" />,name: <I18nText id="pricing.table.feature.subscription.quotes" />,{
      id: 5,name: <I18nText id="pricing.table.feature.subscription.ndc" />,];

  const getCurrentPlan = currentPlan && currentPlan.name;

  const newPlansCard = planData.map(plan => {
    const matchPlan = plan.name === getCurrentPlan;
    return (
      <>
        <Card
          className="billing-plans__plans-card"
          size="normal"
          version="v2"
          title={plan.name}
          headerCenter={true}
          key={plan.id}
        >
          {matchPlan ? (
            <div className="billing-plans__current-plan-icon">
              <img src={greenCheck} alt="check" />
            </div>
          ) : null}
          <div className="billing-plans__plans-card-title">
            <sup>US$</sup>
            {plan.price}
            <sub>
              /<I18nText id="pricing.plans.misc.month" />
            </sub>
          </div>

          <div className="billing-plans__plans-card-features-wrapper">
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.searches" />
              <span className="billing-plans__features-access">
                {plan.freeSearches}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.bookings" />
              <span className="billing-plans__features-access">
                {plan.freeBookings}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.profiles" />
              <span className="billing-plans__features-access">
                {plan.travelerProfiles}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.tickets" />
              <span className="billing-plans__features-access">
                {plan.supportTickets}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.phone" />
              <span className="billing-plans__features-access">
                {plan.supportByPhone}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.channels" />
              <span className="billing-plans__features-access">
                {plan.supplierChannels}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.domain" />
              <span className="billing-plans__features-access">
                {plan.customDomain}
              </span>
            </div>
          </div>

          <div className="billing-plans__plans-card-actions">
            {!matchPlan ? (
              <div>
                <BaseModal
                  linkText={<I18nText id="pricing.plans.actions.select" />}
                  linkClassName="billing-plans__plans-card-actions-button"
                  open={modalOpen}
                  onModalClose={() => setModalOpen(false)}
                  onModalOpen={() => setModalOpen(true)}
                  header={
                    <I18nText id="pricing.plans.actions.confirmationText" />
                  }
                  size="small"
                  showCloseIcon={false}
                  key={plan.id}
                >
                  <div className="col-12">
                    <Button
                      version="v2"
                      type="accent"
                      size="normal"
                      label={I18n.t('shared.action.confirm')}
                      key={plan.id}
                      onClick={() => {
                        selectPlan(plan);
                      }}
                    />
                    <Button
                      version="v2"
                      size="normal"
                      label={I18n.t('shared.action.cancel')}
                      onClick={() => setModalOpen(false)}
                    />
                  </div>
                </BaseModal>
              </div>
            ) : null}
          </div>
        </Card>
      </>
    );
  });

  const pricingTable = () => {
    return (
      <div>
        <div className="container-full billing-plans__pricing-table">
          <Card size="full" version="v2" key={planOptions.id}>
            <div className="billing-plans__table-header">
              <I18nText id="pricing.plans.sub_title" />
            </div>
            <table className="billing-plans__table-body">
              <thead>
                <tr>
                  <th className="billing-plans__table-sub-header">
                    <I18nText id="pricing.table.feature.header" />
                  </th>
                  {tableHeader.map(({ name,id }) => (
                    <th className="billing-plans__table-sub-header" key={id}>
                      {name}
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {planOptions.map(
                  ({
                    id,name,isFree,isBasic,isStandard,isProfessional,isCustom,}) => (
                    <tr key={id}>
                      <td className="billing-plans__table-data">{name}</td>
                      <td className="billing-plans__table-plan">
                        <img src={isFree} alt="check" />
                      </td>
                      <td className="billing-plans__table-plan">
                        <img src={isBasic} alt="check" />
                      </td>
                      <td className="billing-plans__table-plan">
                        <img src={isStandard} alt="check" />
                      </td>
                      <td className="billing-plans__table-plan">
                        <img src={isProfessional} alt="check" />
                      </td>
                      <td className="billing-plans__table-plan">
                        <img src={isCustom} alt="check" />
                      </td>
                    </tr>
                  ),)}
              </tbody>
            </table>
          </Card>
        </div>
      </div>
    );
  };

  return (
    <div className="billing-plans">
      <div>
        <div className="grid">
          <div className="col-12 offset-xlg-1 offset-lg-1 offset-md-1 offset-sm-1 offset-xs-1 offset-xxs-1">
            <div className="billing-plans__plans-header">
              <I18nText id="pricing.plans.title" />
            </div>
          </div>
        </div>
        <div className="billing-plans__plans-wrapper">
          {currentPlan && newPlansCard}
        </div>
      </div>
      {pricingTable()}
    </div>
  );
};

Plans.propTypes = {
  currentPlan: PropTypes.shape({
    name: PropTypes.string,identifier: PropTypes.string,id: PropTypes.number,}).isRequired,affiliateId: PropTypes.number.isRequired,};

export default Plans;

我想获取所选卡的ID并将其传递给模式。在单击第一个按钮即卡片模式的确认按钮时,卡片将显示为选中状态,并带有勾号。像每张卡中一样,都有“选择计划”按钮,可打开模式对话框以确认用户是否确实要选择计划。如果他选择是,则获取特定卡的ID,然后将该ID传递给selectPlan函数以选择特定卡作为计划。在模式的第一个按钮中的现有代码库中,我具有一个onClick函数,该函数将特定的选定计划发送到selectPlan(plan)这样的selectPlan函数。但是,尽管我使用相应的模态选择了哪张卡,但现在我只得到ID为2或6的卡,尽管有5张ID为2、3、4、5、6的卡。这意味着在获取特定卡时会遇到一些问题在当前实施中选择了卡ID。我想知道我应该在当前代码中进行哪些更改,以获取特定的所选Card ID,并使用onClick函数将其传递到相应的模式按钮,以表示使用selectPlan(plan)函数选择的计划。这是“计划”用户界面:

enter image description here

解决方法

  const [plans,setPlans] = useState([]);
  const [currentPlan,setCurrentPlan] = useState([]);
  const [modalOpen,setModalOpen] = useState(false);
  const [selectedPlan,setSelectedPlan] = useState();

  const fetchPlans = async () => {
    const { data } = await httpClient.get(
    const Plans = ({ affiliateId }) => {
                  linkClassName="billing-plans__plans-card-actions-button"
                  open={modalOpen}
                  onModalClose={() => setModalOpen(false)}
                  onModalOpen={() => {
                    setSelectedPlan(plan);
                    setModalOpen(true);
                  }}
                  header={
                    <I18nText id="pricing.plans.actions.confirmationText" />
                  }
    const Plans = ({ affiliateId }) => {
                      label={I18n.t('shared.action.confirm')}
                      key={plan.id}
                      onClick={() => {
                        selectPlan(selectedPlan);
                      }}
                    />
                    <Button
,
import React,{ useEffect,useState } from 'react';
import { I18nText,Card,BaseModal,Button } from '@wtag/react-comp-lib';
import PropTypes from 'prop-types';
import greenCheck from 'affiliateIcons/green-check.svg';
import doneMark from '../../../../assets/images/done-24px.svg';
import routes from '../../../shared/routes';
import httpClient from '../../../shared/libraries/httpClient';

const Plans = ({ affiliateId }) => {
  const [plans,setSelectedPlan] = useState();

  const fetchPlans = async () => {
    const { data } = await httpClient.get(
      routes.billing.changePlan.fetch({ affiliate_id: affiliateId }),);
    setPlans(data.plans);
    setCurrentPlan(data.currentPlan);
  };

  const selectPlan = async plan => {
    const { data } = await httpClient.put(
      routes.billing.changePlan.update({
        id: plan.id,affiliate_id: affiliateId,}),);

    if (data.error === null) {
      fetchPlans(data.currentPlan);
      setModalOpen(false);
    }
  };

  useEffect(() => {
    fetchPlans();
  },[]);

  const data = [
    {
      id: 0,identifier: 'free-2020',name: <I18nText id="pricing.plans.name.free" />,planTitle: 'free',price: '00',freeSearches: <I18nText id="pricing.plans.features.unlimited" />,freeBookings: <I18nText id="pricing.plans.features.unlimited" />,travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,supportTickets: <I18nText id="pricing.plans.features.available" />,supportByPhone: '-',supplierChannels: '-',customDomain: '-',active: true,},{
      id: 1,identifier: 'basic-2020',name: <I18nText id="pricing.plans.name.basic" />,planTitle: 'basic',price: '29',supplierChannels: '1',active: false,{
      id: 2,identifier: 'standard-2020',name: <I18nText id="pricing.plans.name.standard" />,planTitle: 'standard',price: '59',supportByPhone: '1hr/mo',supplierChannels: '2',{
      id: 3,identifier: 'professional-2020',name: <I18nText id="pricing.plans.name.professional" />,planTitle: 'professional',price: '99',supportByPhone: '3hr/mo',supplierChannels: '5',customDomain: 'Yes',{
      id: 4,identifier: 'custom-2020',name: <I18nText id="pricing.plans.name.custom" />,planTitle: 'custom',price: '-',supportByPhone: <I18nText id="pricing.plans.features.unlimited" />,supplierChannels: <I18nText id="pricing.plans.features.unlimited" />,customDomain: <I18nText id="pricing.plans.features.available" />,];

  const planData = data.map(d => {
    const correspondingPlan = plans.filter(
      plan => d.identifier === plan.identifier,)[0];
    if (correspondingPlan) {
      return { ...d,...correspondingPlan };
    }
    return d;
  });

  const tableHeader = [
    { id: 0,name: <I18nText id="pricing.table.header.free" /> },{ id: 1,name: <I18nText id="pricing.table.header.basic" /> },{ id: 2,name: <I18nText id="pricing.table.header.standard" /> },{ id: 3,name: <I18nText id="pricing.table.header.professional" /> },{ id: 4,name: <I18nText id="pricing.table.header.custom" /> },];

  const planOptions = [
    {
      id: 0,name: <I18nText id="pricing.table.feature.subscription.search" />,isFree: doneMark,isBasic: doneMark,isStandard: doneMark,isProfessional: doneMark,isCustom: doneMark,name: <I18nText id="pricing.table.feature.subscription.bookings" />,name: <I18nText id="pricing.table.feature.subscription.traveler" />,name: <I18nText id="pricing.table.feature.subscription.corporate" />,name: <I18nText id="pricing.table.feature.subscription.quotes" />,{
      id: 5,name: <I18nText id="pricing.table.feature.subscription.ndc" />,];

  const getCurrentPlan = currentPlan && currentPlan.name;

  const newPlansCard = planData.map(plan => {
    const matchPlan = plan.name === getCurrentPlan;
    return (
      <>
        <Card
          className="billing-plans__plans-card"
          size="normal"
          version="v2"
          title={plan.name}
          headerCenter={true}
          key={plan.id}
        >
          {matchPlan ? (
            <div className="billing-plans__current-plan-icon">
              <img src={greenCheck} alt="check" />
            </div>
          ) : null}
          <div className="billing-plans__plans-card-title">
            <sup>US$</sup>
            {plan.price}
            <sub>
              /<I18nText id="pricing.plans.misc.month" />
            </sub>
          </div>

          <div className="billing-plans__plans-card-features-wrapper">
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.searches" />
              <span className="billing-plans__features-access">
                {plan.freeSearches}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.bookings" />
              <span className="billing-plans__features-access">
                {plan.freeBookings}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.profiles" />
              <span className="billing-plans__features-access">
                {plan.travelerProfiles}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.tickets" />
              <span className="billing-plans__features-access">
                {plan.supportTickets}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.phone" />
              <span className="billing-plans__features-access">
                {plan.supportByPhone}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.channels" />
              <span className="billing-plans__features-access">
                {plan.supplierChannels}
              </span>
            </div>
            <div className="billing-plans__plans-card-features">
              <I18nText id="pricing.plans.features.domain" />
              <span className="billing-plans__features-access">
                {plan.customDomain}
              </span>
            </div>
          </div>

          <div className="billing-plans__plans-card-actions">
            {!matchPlan ? (
              <div>
                <BaseModal
                  linkText={<I18nText id="pricing.plans.actions.select" />}
                  linkClassName="billing-plans__plans-card-actions-button"
                  open={modalOpen}
                  onModalClose={() => setModalOpen(false)}
                  onModalOpen={() => {
                    setSelectedPlan(plan);
                    setModalOpen(true);
                  }}
                  header={
                    <I18nText id="pricing.plans.actions.confirmationText" />
                  }
                  size="small"
                  showCloseIcon={false}
                  key={plan.id}
                >
                  <div className="col-12">
                    <Button
                      version="v2"
                      type="accent"
                      size="normal"
                      label={I18n.t('shared.action.confirm')}
                      key={plan.id}
                      onClick={() => {
                        selectPlan(selectedPlan);
                      }}
                    />
                    <Button
                      version="v2"
                      size="normal"
                      label={I18n.t('shared.action.cancel')}
                      onClick={() => setModalOpen(false)}
                    />
                  </div>
                </BaseModal>
              </div>
            ) : null}
          </div>
        </Card>
      </>
    );
  });

  const pricingTable = () => {
    return (
      <div>
        <div className="container-full billing-plans__pricing-table">
          <Card size="full" version="v2" key={planOptions.id}>
            <div className="billing-plans__table-header">
              <I18nText id="pricing.plans.sub_title" />
            </div>
            <table className="billing-plans__table-body">
              <thead>
                <tr>
                  <th className="billing-plans__table-sub-header">
                    <I18nText id="pricing.table.feature.header" />
                  </th>
                  {tableHeader.map(({ name,id }) => (
                    <th className="billing-plans__table-sub-header" key={id}>
                      {name}
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {planOptions.map(
                  ({
                    id,name,isFree,isBasic,isStandard,isProfessional,isCustom,}) => (
                    <tr key={id}>
                      <td className="billing-plans__table-data">{name}</td>
                      <td className="billing-plans__table-plan">
                        <img src={isFree} alt="check" />
                      </td>
                      <td className="billing-plans__table-plan">
                        <img src={isBasic} alt="check" />
                      </td>
                      <td className="billing-plans__table-plan">
                        <img src={isStandard} alt="check" />
                      </td>
                      <td className="billing-plans__table-plan">
                        <img src={isProfessional} alt="check" />
                      </td>
                      <td className="billing-plans__table-plan">
                        <img src={isCustom} alt="check" />
                      </td>
                    </tr>
                  ),)}
              </tbody>
            </table>
          </Card>
        </div>
      </div>
    );
  };

  return (
    <div className="billing-plans">
      <div>
        <div className="grid">
          <div className="col-12 offset-xlg-1 offset-lg-1 offset-md-1 offset-sm-1 offset-xs-1 offset-xxs-1">
            <div className="billing-plans__plans-header">
              <I18nText id="pricing.plans.title" />
            </div>
          </div>
        </div>
        <div className="billing-plans__plans-wrapper">
          {currentPlan && newPlansCard}
        </div>
      </div>
      {pricingTable()}
    </div>
  );
};

Plans.propTypes = {
  currentPlan: PropTypes.shape({
    name: PropTypes.string,identifier: PropTypes.string,id: PropTypes.number,}).isRequired,affiliateId: PropTypes.number.isRequired,};

export default Plans;

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...