# Hooks

### 简单用法

```typescript
const app = () => {
  const [state, actions] = useService(DemoService)
  // state.count 
  // actions.add, actions.reset, actions.setCount ...
  return <div>{state.count}</div>
}
// 等价于：
const app2 = () => {
  // 手动使用container获取DemoService的实例，切忌不可直接new DemoService
  const demoService = container.resolveInScope(DemoService)
  const [state, actions] = useServiceInstance(demoService)
  // ...
}
```

### 使用Selector

上述例子中，当state变化的时候，组件也会重新渲染，但是有的时候，全部重新是一种浪费，因此这里也实现了一个类型于react-redux里面的`mapStateToProps` 的筛选函数：

```typescript
const app =() => {
  // 只有当count变化的时候，
  const [count, actions] = useService(DemoService, state => state.count)
  // count 
  // actions.add, actions.reset, actions.setCount ...
  return <div>{count}</div>
}
// 等价于
const app2 = () => {
  // 手动使用container获取DemoService的实例，切忌不可直接new DemoService
  const demoService = container.resolveInScope(DemoService)
  const [count, actions] = useServiceInstance(demoService, state => state.count)
  // ...
}
```

特别的，当你完全不想让state的变化触发重渲染的时候可以这样：

```typescript
const [,actions] = useService(DemoService, () => undefined)
// 等价于：
const actions = useService(DemoService)
// 等价于：
const [,actions] = useServiceInstance(demoService, () => undefined)
// 等价于：
const actions = useServiceInstance(demoService)
```

### 限定Scope

默认注入都是单例（Singleton）,可以手动修改：

```typescript
const app =() => {
  const [count] = useService(DemoService, state => state.count,{scope: Transient})
  const [state, actions] = useService(DemoService, {scope: Transient})
  useEffect(() => actions.add(1), [])
  // count 
  // actions.add, actions.reset, actions.setCount ...
  return <div> count1: {count}, count2: {state.count} </div>
  // count1: 0, count2: 1
}
```

{% hint style="info" %}
scope预定义的值有：`Singleton`， `Transient`,  `Request`， 也可以使用自定义的scope，自定义scope都是单例的，相同scope获取的实例是一样的，不同scope获取的实例不同，Demo（<https://codesandbox.io/s/service-x-scope-8oool>）
{% endhint %}

{% hint style="info" %}
Transient注入的实例是跟随组件生命周期的，当组件unmount的时候，注入实例也会被销毁。
{% endhint %}

{% hint style="info" %}
当scope为单例情况（非Transient or Request)，options中可以设置resetOnUnmount参数，代表当前store中的state会随着组件的unmount进行重置，并且在组件unmount到mount这段时间里，store会处于休眠状态，不响应任何外部调用或者Observable事件。
{% endhint %}

{% hint style="info" %}
实例如何获取：`useService`返回数组的第三项：

```typescript
const [state, actions, service] = useService(DemoService, {scope: Transient})
```

然后就可以把这个service传递给子组件，子组件`useServiceInstance`就能注入同一个service实例了。
{% endhint %}
