簡體   English   中英

如何使用 {children} 將 React Component 道具傳遞給子 function?

[英]How to pass React Component prop to child function using {children}?

我是 React 的新手,所以這可能很明顯,但我不能通過道具傳遞給從其父級創建組件的 function。

我可以將道具傳遞給子組件,但同樣不適用於函數。

我有<Subscription>我可以通過 arguments 像這樣,從它的父post

<Subscription auth={auth} stripeAmount={post.amount} stripePlanId={post.planid}/>

這將創建一個 Stripe 訂閱。 我想限制訂閱以訂閱我通過以下方式訂閱的stripePlanId

class Subscription extends React.Component {

  // https://stripe.com/docs/checkout#integration-custom
  componentDidMount() {
    this.stripeCheckout = window.StripeCheckout.configure({
      ...etc...
      email: this.props.auth.email,
    })
  }

  newSubscription = () => {
    var stripePlanId = this.props.stripePlanId;
    this.stripeCheckout.open({
      amount: this.props.stripeAmount, // in cents
      description: this.props.stripePlanId,
      token: function(token){
        createSubscription(token, stripePlanId)
      }
    })
  }

 ..etc..

這很好用。 But now to pass through the stripePlanId I can't find out how to pass the stripePlanId through since it renders via a function - this {children} argument seems to only pass in the function, and attempting to add arguments causes errors that they are not它期望對傳遞的 arguments 起作用的函數:

const FireflySubscription = ({children}) => (
  <FirebaseAuth>
    { ({isLoading, error, auth}) => {
      if (error || isLoading || !auth) {
        //it pushes these arguments to the parent function
        return children({ 
          error,
          isLoading,
          subscription: null,
        })
      }

      // the issue - how to populate this?
      const stripePlanId = ""  

      // when working this should return the subscription for only this planId
      if (stripePlanId) {
        return <FirestoreCollection
        path="subscriptions"
        filter={[['createdBy', '==', auth.uid], ['stripePlanId','==', stripePlanId]]}
      >
        { ({error, isLoading, data}) => {
          return children({
            error,
            isLoading,
            subscription: data.length > 0 ? data : null,
          })
        }}
      </FirestoreCollection>

      }

      return <FirestoreCollection
        path="subscriptions"
        filter={['createdBy', '==', auth.uid]}
      >
        { ({error, isLoading, data}) => {
          return children({
            error,
            isLoading,
            subscription: data.length > 0 ? data : null,
          })
        }}
      </FirestoreCollection>

    }}
  </FirebaseAuth>
)

export default FireflySubscription

我試圖用另一種方法通過它,但“范圍”沒有通過:

getPostSubscriptions = stripePlanId => {
    return <FireflySubscription>
// it gets these arguments from FireflySubscription function above
    { ({error, isLoading, subscription}) => { 
      if (error) {
        return <Error error={error} />
      }

      if (isLoading) {
        return <p>loading...</p>
      }

      if (!subscription) {
        return <div>
          <p><strong>Subscribe to get paid features</strong></p>
          ..etc...
        </div>
      }

      ..etc...

    }}
  </FireflySubscription>
  }

  render() {
    return this.getPostSubscriptions(this.props.stripePlanId)
  }
}

任何線索都非常感謝! 如果有幫助,我正在改編的原始代碼來自https://github.com/sampl/firefly

使用渲染道具

術語“render prop”指的是一種在 React 組件之間共享代碼的技術,使用值為 function 的 prop。

帶有 render prop 的組件需要一個 function ,它返回一個 React 元素並調用它,而不是實現自己的渲染邏輯。

ParentPost 組件:

const ParentPost = () => {
    <Subscription auth={auth} stripeAmount={post.amount} stripePlanId={post.planid}>
        {(stripePlanId) => <FireflySubscription stripePlanId={stripePlanId}/>}
    </Subscription>
};

訂閱組件:在您的渲染方法中,將stripePlanId作為道具傳遞給children

class Subscription extends React.Component {
  // https://stripe.com/docs/checkout#integration-custom
  componentDidMount() {
    this.stripeCheckout = window.StripeCheckout.configure({
      // ...etc...
      email: this.props.auth.email
    });
  }

  newSubscription = () => {
    var stripePlanId = this.props.stripePlanId;
    this.stripeCheckout.open({
      amount: this.props.stripeAmount, // in cents
      description: this.props.stripePlanId,
      token: function(token) {
        createSubscription(token, stripePlanId);
      }
    });
  };
  
  render() {
      <div>
          ...
          {this.props.children(this.props.stripePlanId)}
          ...
      </div>
  }
}

FireflySubscription 組件:在這里,像這樣從父級接收stripePlanId :。

const FireflySubscription = ({children, stripePlanId}) => (
    <FirebaseAuth>
        {({isLoading, error, auth}) => {
            if (error || isLoading || !auth) {
                //it pushes these arguments to the parent function
                return children({
                    error,
                    isLoading,
                    subscription: null,
                })
            }

            
            //const stripePlanId = stripePlanIdFromParent; // dont need this as we are destructuring from props

            // when working this should return the subscription for only this planId
            if (stripePlanId) {
            ...

通過您引用的存儲庫,您似乎正在從 Subscription 組件中呈現FireflySubscription ,例如

class Subscription extends React.Component {
    // other code here

    render() {
       return (
           <FireflySubscription>
               { ({error, isLoading, subscription}) => {
                   /*Some components here*/
               }}
           </FireflySubscription>
       )
    }
}

考慮到上述情況,最簡單的解決方案是將stripePlanId作為道具傳遞給FireflySubscription組件,並在組件內與子組件一起接收它

現在stripePlanId是在Subscription組件中計算出來的,它可以很容易地直接從父級傳遞給FireflySubscription的子級,而不必擔心它會通過 FireflySubscription 路由

所以解決方案看起來像

class Subscription extends React.Component {
    // other code here

    render() {
       return (
           <FireflySubscription stripePlanId={this.props.stripePlanId}>
               { ({error, isLoading, subscription}) => {
                   // stripePlanId can be passed on to any children here using this.props.stripePlanId directly
                   /*Some components here*/
               }}
           </FireflySubscription>
       )
    }
}

現在在 FireflySubscription 中,您將使用它作為

const FireflySubscription = ({children, stripePlanId}) => (
  <FirebaseAuth>
    { ({isLoading, error, auth}) => {
      if (error || isLoading || !auth) {
        //it pushes these arguments to the parent function
        return children({ 
          error,
          isLoading,
          subscription: null,
        })
      }

      if (stripePlanId) {
        return <FirestoreCollection
        path="subscriptions"
        filter={[['createdBy', '==', auth.uid], ['stripePlanId','==', stripePlanId]]}
      >
        { ({error, isLoading, data}) => {
          return children({
            error,
            isLoading,
            subscription: data.length > 0 ? data : null,
          })
        }}
      </FirestoreCollection>

      }

      return <FirestoreCollection
        path="subscriptions"
        filter={['createdBy', '==', auth.uid]}
      >
        { ({error, isLoading, data}) => {
          return children({
            error,
            isLoading,
            subscription: data.length > 0 ? data : null,
          })
        }}
      </FirestoreCollection>

    }}
  </FirebaseAuth>
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM