Skip to content

How to extend a component? create new one, from another with set props #4918

@k1r0s

Description

@k1r0s

Hello there!

  • I have a component modal (a component that needs a reference to perform dom stuff)

  • That modal receives a form component (a component that will update their children)

  • These components are held by a HOC page component that handles the overall state

page -> (
	page-controller (handles both UX logic and business actions)
	modal -> (
		form
	)
)

  • I tried to abstract moth modal component and form component. Modal and Form have some actions that shouldn't be explicitly specified from the page logic:
page -> (
	common-controller (handles UX actions)
	page-controller (handles business actions)
	modal -> (
		form
	)
)


  • I want the common-controller to retrieve elements
  • how do I extend a React element so it is able to
    WiredModal: ({ children }) => (
      <ManagedModal some={arguments.neededForTheViewToWork}>
        {children}
      </ManagedModal>
    ),

However this causes <ManagedModal to mount for every render since <WiredModal is rendered too

in the page

    <WiredModal>
    	<RelevantChildrenForLogic />
    </WiredModal>

I tried to do but still doesn't work:

  const composed = {
    WiredModal: ({ children }) => ManagedModal.prototype.constructor.bind(null, {
      isOpen: data.showForm, 
      title: `${data.isEdit ? "Edit" : "Create new"} material`, 
      onAccept: actions.onFormSubmit, 
      onCancel: actions.onCancelForm,
      children
    })
  }

I want to be allow to do this:
So composed.WiredModal inherits or has specific embedded behaviors that abstract the developer to interact with the modal primitives. I know this is usually achieved with contexts but I wanted to be cool.

<composed.WiredModal>
  <FormGroup bind={data.form} onChange={actions.onFormFieldUpdated}>
    <Flex direction="column">
      {data.form.id && (
        <div class="d-flex gap-4 mb-2">
          <label>Id</label>
          <span data-id>{data.form.id}</span>
        </div>
      )}
      <FormField label="Name" attr="name" />
      <FormField label="Amount" attr="amount" type="number" />
    </Flex>
  </FormGroup>
</composed.WiredModal>

working alternative ugly as fuck but it does the job since WiredModal is used as a js plain function so there is no jsx rendering

{composed.WiredModal({ children: (
  <FormGroup bind={data.form} onChange={actions.onFormFieldUpdated}>
    <Flex direction="column">
      {data.form.id && (
        <div class="d-flex gap-4 mb-2">
          <label>Id</label>
          <span data-id>{data.form.id}</span>
        </div>
      )}
      <FormField label="Name" attr="name" />
      <FormField label="Amount" attr="amount" type="number" />
    </Flex>
  </FormGroup>) 
})}

I'll be using defaultProps so every controller overrides it but this is also inconvenient and has limitations for every modal in the page.

Any ideas?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions