npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ajanuw-react-rxservice

v1.6.1

Published

react service is a react state manager

Downloads

163

Readme

react-rxservice

Use dependency injection to create services, inspired by Angular

Install

$ npm i ajanuw-react-rxservice
$ npm i rxjs

如果你想使用constructor依赖注入

$ npm i reflect-metadata

配置 tsconfig.json

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
  },
}

全局服务

创建全局服务

@Injectable()
class AppService {
  i = 0;
}

@Injectable 立即注册一个全局服务,当数据变化时通知订阅者

订阅全局服务

export default memo(() => {
  const [as] = useService(AppService);

  return (
    <RxService
      builder={() => {
        return (
          <div>
            <p>{as.i}</p>
            <button onClick={() => as.i++}>change</button>
          </div>
        );
      }}
    />
  );
});

RxService 组件会自动订阅全局服务,收到响应时触发更新

局部服务(非全局服务)

创建局部服务

@Injectable({ global: false })
class PS implements ServiceProxy {
  i = 0;
  
  OnCreate() {}
  OnUpdate() {}
  OnDestroy() {}
}

使用Injectable时可以传入一些配置项,将global设置为false注册为局部服务,并且不会立即注册

提供了一些钩子函数,用于监听局部服务的生命周期

订阅局部服务

export default memo(() => {
  const [ps] = useService(PS);

  return (
    <RxService
      services={[PS]}
      global={false}
      builder={() => {
        return (
          <div>
            <p>{ps.i}</p>
            <button onClick={() => ps.i++}>change</button>
          </div>
        );
      }}
    />
  );
});

使用useService时初始化局部服务

RxServiceservices属性用于添加局部服务,global设置为fasle将不会订阅全局服务,如果你需要局部服务并且也需要全局服务可以无视此选项

RxService 被销毁时,services中的所有局部服务也会自动销毁,销毁前会调用 OnDestroy

OnCreate 在组件渲染完成之前触发

其他问题

不想监听服务中的某个属性的变更?

  1. 使用@Ignore装饰器
@Injectable({ global: false })
class PS implements ServiceProxy {

  @Ignore()
  ref_ = React.createRef<any>();
}
  1. 使用autoIgnore配置选项,会自动无视以_结尾的属性
@Injectable({ global: false, autoIgnore: true })
class PS implements ServiceProxy {
  ref_ = React.createRef<any>();
}

在服务中使用其它服务?

  1. 使用constructor依赖注入
import "reflect-metadata";

@Injectable()
class UserinfoService {}

@Injectable()
class AppService {
  constructor(public readonly userinfo: UserinfoService) {}
}
  1. 使用静态属性
@Injectable()
class UserinfoService {
  static ins: UserinfoService;
}

@Injectable()
class AppService {
  userinfo = UserinfoService.ins;
  i = 0;
}
  1. 使用@Late装饰器
@Injectable({ id: "UserinfoService" })
class UserinfoService {
  i = 0;
}

@Injectable()
class AppService {
  @Late("UserinfoService")
  userinfo!: UserinfoService;

  @Late("AfterService")
  after!: any;
}

@Injectable({ id: "AfterService" })
class AfterService {}

@Late装饰器需要提供一个服务的唯一id,如果这个服务已经被初始化则会立即初始化属性(userinfo),否则会一直等到服务初始化时才设置属性(after)

  1. 在组件中使用多个服务?
@Injectable()
class UserinfoService {}

@Injectable()
class AppService {}

@Injectable({ global: false })
class PS {}

export default memo(() => {
  const [ps, as, us] = useService(PS, AppService, UserinfoService);
  return (
    <RxService
      services={[PS]}
      builder={() => {
        return <div></div>;
      }}
    />
  );
});

使用上一次销毁的数据?

只能在局部服务中在这样做!

@Injectable({ global: false })
class PS implements ServiceProxy {
  i = 0;
  OnDestroy() {
    return true;
  }
}

如果在页面销毁时i=10,并且在OnDestroy钩子中返回true,那么下次重启这个服务时,数据不会被初始化而是继续使用上一次的数据,再次进入页面你会直接看到i=10而不是i=0

服务从第一次创建就一直存在于内存中,销毁只是一个状态,在销毁状态下所有的变更都不会通知订阅者

当再次启动销毁状态的服务时,只是取消了销毁状态,数据的初始化取决于上一次OnDestroy钩子的返回值,如果返回true将继续使用以前的数据,否则会重新初始化一个实例,并创建一个新的代理然后触发OnCreate钩子

改变数据时,不想通知订阅者?

@Injectable()
class PS {
  i = 0;

  add() {
    noreact(() => {
      this.i++
    })
  }
}

noreact的钩子函数中,改变数据时不会通知订阅者

作为装饰器使用也可以达到同样的效果

@Injectable()
class PS {
  i = 0;

  @noreact()
  add() {
    this.i++
  }
}

监听属性的变更

  1. Watch 装饰器,监听一个或多个属性的变更
class PS {
  i = 0;
  obj = { i: 0 }

  @Watch(['this.i', 'this.obj.i'])
  watch(newVal: number, oldVal: number, key: string) {
    console.log(key, newVal, oldVal);
  }
}
  1. AutoWatch 自动监听属性变化
class PS implements ServiceProxy {
  i = 0;
  j = 0;

  @AutoWatch()
  watch() {
    this.j = this.i * 2
  }
}

会自动代理哪些对象?

  • Array
  • [object Object]
  • [object Set]
  • [object Map]
  • [object WeakMap]

Run test

$ npm start
$ npm t