InversifyJS icon indicating copy to clipboard operation
InversifyJS copied to clipboard

Any way to use it with create-react-app without ejecting?

Open da1z opened this issue 2 years ago • 4 comments

any way to use inversify with create-react-app without ejecting? especially @inject in parameters

da1z avatar Aug 02 '21 23:08 da1z

The short answer is there's no "one way" but I can share a pattern I've managed to scale out successfully.

Say you have some component props like:

export interface MyComponentProps extends RouteComponentProps<any> {
	id: string | null
	stateManager: MyStateManager
}

Then you have a component such as:

export class MyComponent extends React.Component<MyComponentProps, any> {
	constructor(props: Readonly<MyComponentProps>) {
		super(props)
	}
        render(): any: {
                return (...)
        }
}

Then you have some state management (this is just my pattern you may have some different use):

export interface MyStateManager {...}
import { injectable } from 'inversify'
@injectable()
export class SpecialStateManager implements MyStateManager {...}

So at this point you have a component and an interface and an injectable implementation. Now it is time to wire these together. One way to do this is to establish a container and configure dependencies.

I create a file container.ts with:

import { Container, interfaces } from 'inversify'
...
// the container is created once, witin this module and used throughout the application
export const container = new Container()
...
container.bind<MyStateManager>('MyStateManager').to(SpecialStateManager).inSingletonScope()

Inside App.tsx I would reference the pre-defined container like:

import { container } from '/path/to/container'
...
const App: React.FunctionComponent = () => {
    const myStateManager = container.get<MyStateManager>('MyStateManager')
...
    return (
		<Router basename={process.env.PUBLIC_URL}>
                    <Switch>
                        <Route exact path="/mypage/:id?" render={props => <MyComponent {...props} id={props.match.params.id}  stateManager={myStateManager} />} />

PeteW avatar Aug 11 '21 12:08 PeteW

Sorry I should have mentioned this. The benefit in this case is to allow swappable implementations of the state behind a react component, and swappable implementations of api clients, all driven by 2 REACT_APP_... configurations settings

PeteW avatar Aug 11 '21 12:08 PeteW

I think author asks about "how to run this" (typescript + cra+ inversify) without ejecting))) It's an old issue, now we can use "react-app-rewired" and "customize-cra" packages to achieve this goal. config.overrides.js must contain these lines:

module.exports = {
  webpack: override(
    /* for more info
     * @see babel-plugin-parameter-decorator README
     */
    addDecoratorsLegacy(),
    ...addBabelPlugins("babel-plugin-parameter-decorator"),
    )
}

also, there will be minor problems in typescript, and finally, I can't find a solution for using auto declaration in constructor and using not string keys:

// works fine
private service: SomeService;
constructor(@inject('SomeService') service: SomeService) {
  super(service);
  this.service = service;
}
// doesn't work
constructor(@inject('SomeService') private service: SomeService) {
}

try to find more info for using inversify in components in google, but I don't recommend doing so, because react already has lazy loading, functional components, and hooks system.

Spektr avatar Nov 26 '21 14:11 Spektr

Yes, my question is about using it without decorators or setting cra to accept them. As I understand there are no clear answer yet

da1z avatar Jun 10 '22 07:06 da1z