【问题标题】:How to dynamically set variables in mutation with react-adopt?如何使用 react-adopt 动态设置突变变量?
【发布时间】:2019-05-23 00:48:12
【问题描述】:

在我的组件中,我使用 react-adopt 来编写 graphql 查询和突变,这样我的渲染道具就不会变得太乱。我有以下代码:

这是我的突变,它需要一个参数 - planID。

const CREATE_ORDER_MUTATION = gql`
  mutation CREATE_ORDER_MUTATION($planID: String!) {
    createOrder(planID: $planID) {
      planID
      name
      description
      subscriptionType
      images
      subscriptionType
      pricePerMonth
}
}

这是采用函数,它需要几个突变,其中之一是 createOrder。 Apollo 的工作方式是我需要在这里将变量 prop 传递给 createOrder 组件。问题是,我此时没有planID。 planID 仅在实际组件内部可用。

const Composed = adopt({
  toggleCart: <Mutation mutation={TOGGLE_CART_MUTATION} />,
  createOrder: <Mutation mutation={CREATE_ORDER_MUTATION} />,
});

我的组件看起来像这样。我在这里有可用的planID,但我怎样才能将它作为参数传递给突变?!

render() {
const { plan } = this.props;
return (
  <Composed>
    {({ toggleCart, createOrder }) => {
      const handleAdd = () => {
        toggleCart();
        Router.push('/waschingmachine');
        createOrder();
      };
      return (
        <StyledPlan>
          <h1>{plan.name}</h1>
          <p>{plan.description}</p>
          <img src={`static${plan.images[0]}`} alt="blue1" />
          <h2>{plan.pricePerMonth / 100} EUR</h2>
          <div className="buttons">
            <Link
              href={{
                pathname: '/plan',
                query: { id: plan.id },
              }}
            >
              <button type="button">info</button>
            </Link>
            <button onClick={handleAdd} type="button">
              Select Plan
            </button>
          </div>
        </StyledPlan>
      );
    }}
  </Composed>
);
}

如果没有办法以这种方式解决它,您将如何以不同的方式解决它?

【问题讨论】:

    标签: reactjs graphql react-apollo


    【解决方案1】:

    您可以通过以下方式将参数通过 react-adopt 方式传递到您的内部 mutations 映射器中:

    // In a nutshell, `react-adopt` allows you to pass props to your `Composed`
    // component, so your inner `mapper` can access those props to pass them to 
    // your <Query> or <Mutation>
    
    // Here's your initial `Composed` component from above
    const Composed = adopt({
      // `planId` is passed from below via props (see `<ContainerComponent />) 
      toggleCart: ({ planId, render }) => (
        <Mutation mutation={TOGGLE_CART_MUTATION} variables={{ planId }}>{render}</Mutation>,
        ),
      // `planId` is passed from below via props (see `<ContainerComponent />)
      createOrder: ({ planId, render })=> (
        <Mutation mutation={CREATE_ORDER_MUTATION} variables={{ planId }}>{render}</Mutation>                 
      )
    });
    
    // `<ContainerComponent />` will take a plan as its props and passed `planId` to 
    // the `<Composed />` component
    const ContainerComponent = ({ plan }) => (
      <Composed planId={plan.id}>
        {({ toggleCart, createOrder }) => {      
          const handleAdd = e => {
            e.preventDefault();
            toggleCart();
            // ...
            createOrder();
            // ...
          };
    
          // Whatever your UI needs you can pass them here via here
          return <YourPresentationComponent onClick={handleAdd} />;
        }}
      </Composed>
    )
    
    // Now all you need to do is to pass `plan` from your render() to the 
    // <ContainerComponent /> (This is the render() where you return your 
    render() {
      const { plan } = this.props;
      return <ContainerComponent plan={plan} />
    }
    
    

    希望这有助于解决您的问题!顺便说一句,您还可以获取先前的 mapper 值并将它们作为参数的一部分传递给下一个映射器 fn,见下文:

    const Composed = adopt({ 
      // Here you can retrieve the actual `plan` by using `userId` and pass the result 
      // into your next children mapper fn to consume
      plan: ({ userId, render }) => (
       <Query query={GET_PLAN_GRQPHQL} variables={{ userId }}>{render}</Query>
      ),
      // `plan` is actually coming from above <Query /> component 
      toggleCart: ({ plan, render }) => { //... },
      createOrder: ({ plan, render }) => { //...}
    });
    

    【讨论】:

    • 据我所知,这应该是公认的答案。这演示了如何将变量传递给&lt;Query /&gt; 组件
    【解决方案2】:

    可以使用选项调用在渲染子项中传递的 mutate 函数。 选项可以包括 GraphQL 变异字符串中使用的变量。 [1].

    这意味着你可以像这样调用createOrder突变函数。

    createOrder({ variables: { planID: 'some plan id' } });
    

    鉴于 planID 的动态特性,有多种方法可以实现这一点。其中之一是使用如下数据属性:

    可以为按钮上的计划 ID 设置 data 属性。

    <button onClick={handleAdd} data-planid={plan.id} type="button">
          Select Plan
    </button>
    

    handleAdd 可以重构以从目标数据集属性中获取planid,并使用planID 变量调用createOrder

    const handleAdd = event => {
        const planID = event.target.dataset.planid;
        toggleCart();
        Router.push('/waschingmachine');
        createOrder({ variables: { planID } });
    };
    

    另一种是在按钮的onClick 属性中调用planID 时直接将handleAdd 传递给handleAdd

    <button onClick={() => handleAdd(plan.id)} type="button">
          Select Plan
    </button>
    

    然后更新处理程序

    const handleAdd = planID => {
        toggleCart();
        Router.push('/waschingmachine');
        createOrder({ variables: { planID } });
    };
    

    这两种方法都需要权衡取舍。对于较早的方法,planid 在 DOM 中设置为属性,以后可以读取。 而对于后一种,为 N 个计划创建 N 个处理程序并保存在内存中。

    【讨论】:

      猜你喜欢
      • 2019-12-12
      • 2011-10-28
      • 2013-05-15
      • 2022-01-23
      • 2019-01-29
      • 1970-01-01
      • 1970-01-01
      • 2016-10-23
      • 1970-01-01
      相关资源
      最近更新 更多