# @typeclient/react

React驱动支持。推荐采用FunctionComponent + hooks模式编写应用。

# Hooks

新增基于路由级别的hooks

# useReactiveState

对于任意被@vue/reactivity包裹过的对象都将返回响应式的数据对象供react内部使用。

import { reactive, ref } from '@vue/reactivity';
const state = reactive({ count: 0 });
const num = ref(100);
const { count, num } = useReactiveState(() => {
  return {
    count: state.count,
    num: num.value
  }
});
return <div>{count} - {num}</div>

也可以通过 import { useReactiveState } from '@typeclient/react-effect'获得。

# useContextState

返回请求级别ctx上数据的响应。

@injectable()
class ABC {
  test() {
    const { count, status } = useContextState((ctx: Context) => {
      return {
        count: ctx.state.count,
        status: ctx.status.value
      }
    })
    return <div>{count} - {status}</div>
  }
}

# useApplicationContext

返回ctx对象

const ctx = useApplicationContext() as Context;

# useContextEffect

路由生命周期,类似组件生命周期。它接受一个回调函数,表示路由created生命周期,如果返回一个回调函数,则表示路由destroy生命周期。

useContextEffect(() => {
  console.log('router ready');
  return () => console.log('router destroyed');
})

# useComponent

为react提供一种新的组件模式

import { Component, ComponentTransform } from '@typeclient/react';
@Component()
class ttt implements ComponentTransform {
  @inject(Abc) private Abc: Abc;
  public render(props: React.PropsWithoutRef<{}>) {
    return React.createElement('div', null, '123evio-' + this.Abc.abc());
  }
}

调用:










 




import { inject } from 'inversify';
import { Route, Controller, useMiddleware } from '@typeclient/core';
import { useComponent } from '@typeclient/react';
@Controller()
@useMiddleware(DemoMiddleware)
class router {
  @inject(ttt) private readonly ttt: ttt;
  @Route('/test')
  test() {
    const Cmp = useComponent(this.ttt);
    return <Cmp />
  }
}

# useSlot

它支持Slot插槽模式,我们可以通过useSlot获得ProviderConsumer。它是一种通过消息传送节点片段的模式。

const { Provider, Consumer } = useSlot(ctx.app);
<Provider name="foo">provider data</Provider>
<Consumer name="foo">placeholder</Consumer>

然后编写一个IOCComponent或者传统组件。

// template.tsx
import { useSlot } from '@typeclient/react';
@Component()
class uxx implements ComponentTransform {
  render(props: any) {
    const { Consumer } = useSlot(props.ctx);
    return <div>
      <h2>title</h2>
      <Consumer name="foo" />
      {props.children}
    </div>
  }
}

最后在Controller上调用

import { inject } from 'inversify';
import { Route, Controller } from '@typeclient/core';
import { useSlot } from '@typeclient/react';
import { uxx } from './template.tsx';
@Controller()
@Template(uxx)
class router {
  @inject(ttt) private readonly ttt: ttt;
  @Route('/test')
  test() {
    const { Provider } = useSlot(props.ctx);
    return <div>
      child ...
      <Provider name="foo">
        this is foo slot
      </Provider>
    </div>
  }
}

你能看到的结构如下:

<div>
  <h2>title</h2>
  this is foo slot
  <div>child ...</div>
</div>