Passing callback functions while registering react components in builder

We have react components with callback functions as props inside NextJS site. How to pass the callbacks (syntax) while registering the react components in builder.

Thanks.

Hi @dharmaraju could you clarify what you are trying to do with these callback functions? What is the use case for needing them to be passed into Builder?

hey TimG and @dharmaraju - I was just working on integrating this in our NextJS codebase, maybe I can share how we are utilizing functions and React context.

<BuilderComponent
   model={Builder.previewingModel || 'builder-page'}
   context={{
       callbackFn,
   }} />

Then, in your custom component, you can access these via the builderState prop that is passed.

function CustomComponent(props) {
  const onClick = () => {
    props.builderState.context.callbackFn();
  }
  return (
     <button onClick={onClick}>custom button</button>
  )
}


1 Like

Awesome @will! Thank you for that response, @dharmaraju let us know if that works for you!

Thanks @will and @TimG. Can you tell where to define callbackFn as its throwing function initialization error.?

const Page = () => {

  function CustomComponent(props) {

    const onClick = () => {

      props.builderState.context.callbackFn();

    };

    return <button onClick={onClick}>custom button</button>;

  }

  Builder.registerComponent(CustomComponent, {

    name: "CustomComponent",

  });

  return (

    <>

      {" "}

      <BuilderComponent

        model={Builder.previewingModel || "builder-page"}

        context={{

          callbackFn,

        }}

      />

    </>

  );

};

export default Page;

We have a site developed in NextJS already. Now we want to edit those NextJS pages, means want to add some new sections in the middle of the pages from Builder and want to edit the existing sections(components in react) using Builder.
So to edit the existing NextJS page, I have created a model called section and could add it either on top or bottom of the body of the page as it depends on where you have imported in the page in the code. So this way we can add only an editable section but cant add the new sections in the middle of the existing page.

So I thought of registering all the sections (react components) in builder and drag one after the other. But our react components(Sections) are containing some props like functions and objects.
Ex:

<Section1
handleSubmit={handleSubmit}
inputVal={inputVal=}
area={{
    city:"test city",
    county:"test county",
    StateCode:"CA"
}}
/>

So how to register the above kind of react components in builder with same props and without effecting the existing functionality?
Or is there any way we can edit any section in the existing NextJS page(created out of builder) in builder?

const Page = () => {
  return (
    <>
      <Section1
        handleSubmit={handleSubmit}
        inputVal={inputVal}
        area={{
          city:"test city",
          county:"test county",
          StateCode:"CA"
        }}
      ></Section1>
    <Section2 ></Section2>
    <Section3></Section3>
    </>
  )
};

export default Page;

@TimG any help here?

hey @dharmaraju it looks like you are passing callbackFn to the <BuilderComponent/> but not defining it… I assume you have handleSubmit that is being passed as an attribute to the <Section/> as a method somewhere in your code? You would probably want something like this:

const Page = () => {

  function CustomComponent(props: any) {
    const handleSubmit = () => {
      props.builderState.context.passedHandleSubmit();
    };
    return (
      <Section
        handleSubmit={handleSubmit}
        inputVal={props?.inputVal}
        area={{
          city: props?.area?.city,
          county: props?.area?.count,
          StateCode: props?.area?.stateCode
        }}/>
    )
  }

  Builder.registerComponent(CustomComponent, {
    name: "CustomComponent",
    inputs: [
       {
        name: "inputVal",
        type: "string" 
       }, {
        name: "area",
        type: "object",
        subFields: [
            {
                name: "city",
                type: "string",
                defaultValue: "San Francisco"
            },
            {
                name: "county",
                type: "string",
                defaultValue: "San Francisco"
            },
            {
                name: "stateCode",
                type: "string",
                defaultValue: "CA"
            },
        ]
       } 
    ]
  });
  
  function passedHandleSubmit () {
    //include your handle submit logic 
  }
  return (
    <>
      <BuilderComponent
        model="page"
        context={{ passedHandleSubmit }}
      />
    </>
  );
};
export default Page;

Try that out and see if it works for you

Awesome! It worked. Thanks @TimG .
And we have a component to register which has an input as array of objects(ex:100 items with bigger objects having more number of keys), how to register this and pass as input?

Ex:[
{
    a: "1",
    b: "2",
    c: "1",
    d
    e
    ...
},
{
    a: "1",
    b: "2",
    c: "1",
    d
    e
    ...
},
.
.
.
.
.
]

And is the way (mentioned in the earlier question like registering all the existing react components in builder and drag one after the other) we are following to edit the existing NextJS page in builder good one? If not, would be helpful if you can tell other way.

First, wanted to just call out for any other users who find this page, that you can find a clarification on this forum post: Accessing builderState in custom components withChildren - #2 by will

While using props.builderState.context.callbackFn() will work, Builder also provides the BuilderStoreContext for this.

So instead of

const builderState = useContext(BuilderStoreContext);

const handleSubmit = () => {
    builderState.context.passedHandleSubmit();
};

You can use:

const handleSubmit = () => {
   props.builderState.context.passedHandleSubmit();
};

Either works, but BuilderStoreContext provides a convenient, Builder-provided way to access the context of your app

@dharmaraju to answer your question about input type, we do have a json type or even a string might work assuming your stringify and parse your input as needed. What is the use case for this input? How will it be accessed and used within Builder and/or your app?