简体   繁体   English

使用 tsyringe 与 TypeScript 进行依赖注入反应

[英]React with TypeScript using tsyringe for dependency injection

I am currently having trouble with my React TypeScript project.我目前在使用 React TypeScript 项目时遇到问题。

I created my project with npx create-react-app my-app --template typescript .我使用npx create-react-app my-app --template typescript创建了我的项目。

I recently added tsyringe for dependency injection and was trying to implement it for an apiService.我最近为依赖注入添加了 tsyringe,并试图为 apiService 实现它。 After following the readme( https://github.com/microsoft/tsyringe#injecting-primitive-values-named-injection ) for adding primitive values I have hit a block.在按照自述文件( https://github.com/microsoft/tsyringe#injecting-primitive-values-named-injection )添加原始值后,我遇到了障碍。 I already add experimentalDecorators and emitDecoratorMetadata to my tsconfig.json file with no success.我已经将experimentalDecoratorsemitDecoratorMetadata添加到我的tsconfig.json文件,但没有成功。

The error actual error I am encountering is:我遇到的错误实际错误是:

./src/ts/utils/NetworkService.ts 9:14
Module parse failed: Unexpected character '@' (9:14)
File was processed with these loaders:
 * ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
| 
| let NetworkService = (_dec = singleton(), _dec(_class = (_temp = class NetworkService {
>   constructor(@inject('SpecialString')
|   value) {
|     this.str = void 0;

I am fairly sure this problem is caused by Babel, however I created this with npm create react-app --template typescript and do not seem to have access to the Babel configuration.我相当确定这个问题是由 Babel 引起的,但是我使用 npm create react-app --template typescript 创建了这个并且似乎无法访问 Babel 配置。

NetworkService.ts网络服务.ts

@singleton()
export default class NetworkService
{

    private str: string;
    constructor(@inject('SpecialString') value: string) {
        this.str = value;
    }
}

Invocation method调用方法

bob() 
{
    const inst = container.resolve(NetworkService);
}

Registering Class in index.ts在 index.ts 中注册 Class

container.register('SpecialString', {useValue: 'https://myme.test'});


@registry([
    { token: NetworkService, useClass: NetworkService },
])
class RegisterService{}

React-Scripts manages many of the configs related to the project. React-Scripts 管理与项目相关的许多配置。 For many cases, this is fine and actually a nice feature.在许多情况下,这很好,实际上是一个不错的功能。 However, because React-Scripts uses Babel for it's development environment and does not expose the config.但是,因为 React-Scripts 使用 Babel 作为其开发环境并且不公开配置。

You have to run npm run eject to expose the configurations.您必须运行npm run eject以公开配置。

Please note, this is a one-way operation and can not be undone.请注意,这是一种单向操作,无法撤消。 Personally, I prefer more control with my configuration.就个人而言,我更喜欢对我的配置进行更多控制。

After this you can edit the webpack.config.js in the newly created config folder.之后,您可以在新创建的配置文件夹中编辑webpack.config.js

Find the section related to the babel-loader in the dev-environment and add 'babel-plugin-transform-typescript-metadata' to the plugins array .dev-environment找到babel-loader相关的部分,并将'babel-plugin-transform-typescript-metadata'添加到plugins array中。

Instead of eject, you may use a lib that "overrides" some of your params.您可以使用“覆盖”您的某些参数的库,而不是弹出。

I used craco: https://www.npmjs.com/package/@craco/craco我用过 craco: https://www.npmjs.com/package/@craco/craco

Expanding on Jordan Schnur's reply, here are some more pitfalls I encountered when adding TSyringe to my CRA app:扩展 Jordan Schnur 的回复,以下是我在将 TSyringe 添加到我的 CRA 应用程序时遇到的更多陷阱:

Use import type with @inject将导入类型与 @inject 一起使用

If you get this error "TS1272: A type referenced in a decorated signature must be imported with 'import type' or a namespace import when 'isolatedModules' and 'emitDecoratorMetadata' are enabled."如果您收到此错误“TS1272:在启用 'isolatedModules' 和 'emitDecoratorMetadata' 时,必须使用 'import type' 或命名空间导入来导入修饰签名中引用的类型。” replace import with import type for the offending imports.对于有问题的进口,用import type替换import You will encounter this when working with @inject Eg replace import { IConfig } from "iconfig" with import type { IConfig } from "iconfig"使用@inject时会遇到这种情况,例如将import { IConfig } from "iconfig"替换为import type { IConfig } from "iconfig"

Fixing Jest修复笑话

Your Jest tests will also break with TSyringe, especially when using @inject .您的 Jest 测试也会因 TSyringe 而中断,尤其是在使用@inject时。 I got the error "Jest encountered an unexpected token" with details constructor(@((0, _tsyringe.inject)("")) ("@" marked as the offending token). I took the following steps to fix that in CRA:我收到错误“Jest 遇到了意外的令牌”,详细信息constructor(@((0, _tsyringe.inject)("")) (“@”标记为有问题的令牌)。我采取了以下步骤在 CRA 中修复该问题:

Add the line import "reflect-metadata";添加行import "reflect-metadata"; to the top of the file src/setupTests.ts到文件src/setupTests.ts的顶部

In config/jest/babelTransform.js replace line 18 and following:config/jest/babelTransform.js替换第 18 行及以下内容:

From

    
    module.exports = babelJest.createTransformer({
      presets: [
        [
          require.resolve('babel-preset-react-app'),
          {
            runtime: hasJsxRuntime ? 'automatic' : 'classic',
          },
        ],
      ],
      babelrc: false,
      configFile: false,
    });
    

to:至:

    
    module.exports = babelJest.createTransformer({
      presets: [
        [
          require.resolve('babel-preset-react-app'),
          {
            runtime: hasJsxRuntime ? 'automatic' : 'classic',
          },
        ],
      ],
      plugins: [
        require.resolve('babel-plugin-transform-typescript-metadata')
      ],
      babelrc: false,
      configFile: false,
    });
    

I've created an simpler DI library that doesn't need decorators or polyfill.我创建了一个更简单的 DI 库,它不需要装饰器或 polyfill。 Works with CRA like a charm and has cool React bindings像魅力一样与 CRA 一起工作,并具有很酷的 React 绑定

iti

import { useContainer } from "./_containers/main-app"

function Profile() {
  const [auth, authErr] = useContainer().auth

  if (authErr) return <div>failed to load</div>
  if (!auth) return <div>loading...</div>

  return <div>hello {auth.profile.name}!</div>
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用依赖注入的 React/TypeScript 动态切换语句 - React/TypeScript Dynamic Switch Statement using Dependency Injection 反应依赖注入或类似? - React dependency injection or similar? 使用 React Hooks 进行依赖注入 - Dependency Injection with React Hooks React redux 共享整页依赖注入 - React redux sharing whole pages dependency injection 解决 TypeScript React JS Lint: React Hook useEffect has a missing dependency without using comment to disable lint or without pass dependency - Resolving TypeScript React JS Lint: React Hook useEffect has a missing dependency without using comment to disable lint or without passing dependency React TypeScript 16.8 如何添加对 useEffect() 的依赖 - React TypeScript 16.8 How to add a dependency to useEffect() 我可以将 arguments 提供给 react-app 吗? (React 的依赖注入) - Can I give arguments to a react-app? (dependency injection with React) 如何在 React (TypeScript) 中使用依赖注入组件 - How to use dependency injected component in React (TypeScript) 基于带有承诺和依赖注入的React / Redux构建成熟的应用架构 - Building mature app architecture based on React/Redux with promises and dependency injection 无法让属性依赖注入在 React 项目中工作 - Can't get property dependency injection to work in React project
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM