unadlib / reactant Goto Github PK
View Code? Open in Web Editor NEWA framework for building React applications
Home Page: https://reactant.js.org/
License: MIT License
A framework for building React applications
Home Page: https://reactant.js.org/
License: MIT License
Reactant has been working great for our dependency injection and viewmodules. One thing we haven't figured out from Reactant's documentation, all classes/objects injected are effectively singletons because if 2 classes need the class Foo{}, they get the same instance of it if it already exists in the container. With the constructor injection, how can it request a new object instead of a pre-existing one thats already in the container? I'd prefer not to do useFactory in the modules as the class being injected does have a dependency of its own that is injected.
This might be good to add to the documentation.
For example, how can the 2 classes below, MainView and OtherView get their own instance of Foo?
@injectable({name:"foo"})
class Foo{
....
}
class MainView extends ViewModule {
constructor(protected foo: Foo){ }
component(....)
}
class OtherView extends ViewModule {
constructor(protected foo: Foo) { }
component(....)
}
I'd prefer to avoid:
modules: [
{
provide: "foo",
useFactory: ()=> {return new Foo(...);}
}
]
As our Foo does have a dependency that Reactant is injecting
First of all, congratulations on this library, i like it ;)
Is it possible, in Module, to resolve an another module but not in constructor ?
I want to make a generic plugin for Authentication with options.
export const AuthOptions = Symbol("AuthOptions");
export interface IAuthOptions {
path: string
loginView: Module<ViewModule>
}
const AuhtOptionsDefault: IAuthOptions = {
path: "/login",
loginView: LayoutView /** <== this is default ViewModule */
}
@injectable()
export class AuthModule extends PluginModule {
readonly [storeKey]?: any
authOptions: IAuthOptions;
constructor(
@optional(AuthOptions) options: IAuthOptions
){
super();
this.authOptions = {
...AuhtOptionsDefault,
...options
}
}
provider = (props: PropsWithChildren<any>) => {
const componentView = resolve(this.authOptions.loginView); /** <== how resolve this ? */
return (
<>
<Switch>
<Route path={this.authOptions.path} component={componentView.component} />
</Switch>
{props.children}
</>
)
}
}
I want to make the component this.authOptions.loginView
configurable by the users.
How can i make it ?
thank you.
reactant-last-action
reactant-share
Design a module identity api that can be unsynchronized, and the state in the instance marked by it will not be synchronized
If the synchronized and unsynchronized state is modified in a Redux action, reactant-last-action
sequence counter will count normally and the synchronized state will be sent via reactant-share
.
Since the access to a class's state is via a getter in Reactant, its derived state and that of computed can be implemented in a manner similar to the concept of signals for automatic dependency collection.
The usage is modified as follows:
@injectable()
class Counter {
@state
count = 0;
- @computed((that) => [that.count])
+ @computed
get num() {
return this.count + 1;
}
}
Hi,
Assuming a typical createSharedApp() app, is there a way at runtime for a class to get (or create a new object) from the "main container" for the app? Not sure if the following code is helpful, but typically if I do new Foo() on an object that uses @state/@action, I get errors even if I tried using @autoBind:
Uncaught Error: 'this' in method 'AddFoos' of class 'FooList' decorated by '@action' must be bound to the current class instance.
I am guessing I need to get the object from the container and not do New on it so the @action function is correctly bound to the class. Here is a simple example, although I understand the code could be changed to return a simple Array or Map instead of a FooList but trying to come up with a simple example of wanting to do New myClassName() at runtime instead of constructor injection; This could be good to also add to the documentation.
class Foo{
@state
Name: string = "";
@state
classifier: string = "";
}
class FooList
{
@state
Foos: Array<Foo> = [];
@action
UpdateFoos(foos: Array<Foo>){.....}
}
class FooView{
constructor(inject("AllFoos") allFooList: FooList) {}
get SpecialFoo(): FooList
{
const foolist = new FooList(); //This line would be replaced with getting a new FooList from the container...
foolist.UpdateFoos(this.allFooList.filter((foo)=>......);
return foolist;
}
}
Thank you
As projects become larger, we need a front-end architecture model that can handle multi-process programming. In reactant-share, we can call this a Coworker. Tasks that consume CPU or occupy request limits in the main process can be transferred to the Coworker for execution, and their status is synchronized back to the main process.
We will add interface in packages/reactant-share/src/interfaces.ts
.
interface ISharedAppOptions {
coworker?: {
/**
* Whether to be in coworker.
*/
isCoworker: boolean;
/**
* Importing the injected dependency modules.
*/
modules: ReactModuleOptions[];
/**
* Specify a SharedWorker URL
*/
workerURL?: string;
};
}
For example,
In coworker.ts
createSharedApp({
modules: [],
main: AppView,
render: () => {
//
},
share: {
name: 'SharedWorkerApp',
type: 'SharedWorker',
coworker: {
isCoworker: true,
modules: [],
workerURL: 'coworker.bundle.js',
},
},
});
Is there a way to combine your Framework and Next Js to get a cool SSR?
Click the Back or Forward button on the browser.
all client should sync up the routing state
Just current client changes the routing state
Thank to @ZouYouShun for the report.
Many developers still have concerns about TS and JS decorators. In particular, the decorator is a feature of the language that is not stable over the long term, so support for disabling the decorator in reactant-module
and reactant-di
is open to discussion.
For example,
@injectable()
class Foo {
@state
foo = '';
@action
update(text: string) {
this.foo = text;
}
}
When disabling the decorator, it's equal to:
decorate(
class Foo {
constructor() {
this.foo = '';
decorate(this, {
foo: state,
update: action,
});
}
update(text: string) {
this.foo = text;
}
},
injectable
)
reactant-share
uses a one-to-many client design, which relies on class method
proxies that trigger the server's execution methods.
class Counter {
@state
count = 0;
@action
_increase() {
this.count += 1;
}
@proxy
async increase() {
this._increase();
}
async doSomething() {
await this.increase();
}
}
For developers, the principle of using @proxy
is difficult to grasp, and the decorated methods often have to be newly written in order to have to be asynchronous, thus necessitating a new simple asynchronous method, which is not worth it.
Therefore, reactant-share
requires a more flexible and simple C/S proxy model, and the actor model is well suited for such a design.
class Counter {
@state
count = 0;
@action
increase() {
this.count += 1;
}
async doSomething() {
await spawn(this, 'increase', []);
}
}
To better adapt to the needs of multiprocessing, we want "coworker" to quickly support the multiprocessing module. This would allow for more efficient utilization of multiple modules in high-performance multiprocessing and concurrency, combining them into a higher-performing app.
We can create a proprietary coworker module using createCoworker()
.
const [CounterWorker, CounterWorkerOptions] = createCoworker('Counter');
createSharedApp({
modules: [
{
provide: 'NewProxyCounter',
useClass: ProxyCounter,
},
CounterWorker,
{
provide: CounterWorkerOptions,
useValue: {
useModules: ['NewProxyCounter'],
worker: new Worker(new URL('./counter-coworker.ts', import.meta.url)),
isCoworker: false
} as ICoworkerOptions,
},
],
// more shared app config
});
In order to better control multiple clients through the server port, we would like to add clientIds
to the PortDetector
module of the server port.
I try to subscribe a method from another module but it's not reached
// layout.view.tsx
@injectable()
export class LayoutView extends ViewModule {
@state
drawerOpen: boolean = false
@action
toggleDrawer(){ this.drawerOpen = !this.drawerOpen; }
...
// parametres.service.ts
@injectable()
export class ParametresService {
constructor(
private readonly layout: LayoutView
){
subscribe(this.layout, () => { console.log("this.layout.subscribe"); })
}
...
I expect that the method was called.
if i do this it work
setTimeout(() => {
subscribe(this.layout, () => { console.log("this.layout.subscribe"); })
},1)
But it's not very elegant.
Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.