lube
lube

Reputation: 143

How can I override components from another module?

I want to create multiple applications based on the same codebase. All websites will be pretty much identical, but some of them might have some additional/different logic/templates.

Actually, we are using Java EE/JSF for our projects, but I want to migrate to another "fronted" framework. My goal is to replace the JSF with react Currently, we have 1 project, which is called product and for all customers, we have "projects", which can override the core "product"

For example: We have a dialog in the core codebase, which has 3 fields to fill. One customer needs one field more, but the rest is the same.

So I have 2 two questions:

1. How can I override the components used in the core module?

2. When inheriting a component, is it possible to only override part of the parent template?

Thanks

Upvotes: 6

Views: 13362

Answers (2)

Saša Đurić
Saša Đurić

Reputation: 327

This library solves the problem of overriding react components. https://www.npmjs.com/package/react-component-override

In order to override some component, that component must be wrapped with overridable function.

// CoreComponent.jsx
import { overridable } from 'react-component-override';

export const CoreComponent = overridable((props) => {
   return <div>Core component</div>;
})

Then create an override with createOverrides function and pass it through OverridesProvider.

// Foo.jsx
import {
  createOverrides,
  override,
  OverridesProvider
} from 'react-component-override';
import { CoreComponent } from '../core/CoreComponent.js';

const OverridenCoreComponent = (props) => {
  return (
    <div>Overriden core component</div>
  );
};

const overrides = createOverrides([
    override(CoreComponent, OverridenCoreComponent)
]);

function Foo() {
  return (
    <OverridesProvider overrides={overrides}>
      /* It will actually be OverridenCoreComponent component */
      <CoreComponent />
    </OverridesProvider>
  );
}

Upvotes: 0

Estus Flask
Estus Flask

Reputation: 222498

How can I override the components used in the core module?

Modules cannot be overridden by means of JavaScript alone. This can be fixed at build step by introducing module aliases, e.g. with Webpack. Original component module should be an alias for override component module.

This can be considered a temporary measure because it is unobvious for a developer, needs additional configuration and may become complicated with time.

In order to override specific components with JavaScript, the application should be refactored to make use of dependency injection pattern in some way. Dependency injection container can be provided for entire application via context API or Redux store. E.g. a context can be optionally provided to the application to override those components that are expected to be overridden:

const DepContext = React.createContext({});

const MyApp = props => (
  <DepContext.Provider value={{Foo: MyFoo}}>...</DepContext.Provider>
);

Components that depend on this component receive overridden or original one:

import OriginalFoo from '../components/foo';

const Bar = props => (
  <DepContext.Consumer>
    {({ Foo = OriginalFoo }) => (
      <Foo/>
    )}
  </DepContext.Consumer>
);

When inheriting a component, is it possible to only override part of the parent template?

There's no good way to do this, inherited component should copy and paste the layout:

class Foo extends Component {
  render() {
    return (
      <div>
        Some layout
        <div>Nested layout</div>
      </div>
    );
  }
}

This shouldn't be a problem with fine-grained components, render could be be recomposed with minimal efforts:

class Foo extends Component {
  render() {
    return (
      <SomeFooLayout>
        <NestedFooLayout/>
      </SomeFooLayout>
    );
  }
}

class MyFoo extends Foo {
  render() {
    return (
      <SomeFooLayout>
        <NestedFooLayout/>
        <MoreNestedFooLayout/>
      </SomeFooLayout>
    );
  }
}

Upvotes: 3

Related Questions