Is there a recommended approach to referencing an instantiated class object in React / Nextjs? - node.js

Let's say I have a Node.js library that I need to instantiate in my React app.
const awesomeLibrary = new AwesomeLibrary('someID', options);
awesomeLibrary allows me to do things like awesomeLibrary.configure(), awesomeLibrary.specifyCustomProperty() and awesomeLibrary.fireEvent().
I would like to instantiate it once and then call those methods from the instantiated reference (awesomeLibrary) around my application. What is the best way to that?
Would I instantiate it in top-level entry component (e.g. _app.tsx), export it, import it into other components and call the methods? In order to export it, I'd have to instantiate it outside the component, instead of in the lifecycle of the component. Is that a bad practice?
Alternatively, could I relegate the instantiation to a hook? Say useAwesomeLibrary() in which I instantiate and export the methods? But wouldn't doing that create an instance every time the hook is called from different components?
I'm really not sure how to handle this.

Instantiating class before exporting it is a fairly common practice and one of the possible implementations of singleton in JavaScript/React. For example, you can use popular i18next library in this way:
services/i18n.js:
import i18n from 'i18next';
i18n.init({
// pass translations and other config
});
export default i18n;
_app.js:
import i18n from 'services/i18n';
// snip
<I18NextProvider i18n={i18n} /> // consume already instantiated i18n object
The difference between this and instantiating object in a hook is WHEN it will be instantiated. When you do this in hook, it will instantiate every time you mount component with this hook. When in separate file (module), then it will be once per page load.
Is that a bad practice? I don't know, it depends on how you'd use it. There is nothing bad in doing this per se, and even it has its advantages (in the example above we delegated responsibility of creating and configuring i18n service from _app.js, which is very good from Single Responsibility Principle perspective). But keep in mind that codebase bloated with singletons will probably become hard to maintain.

Related

How to set React states outside React components?

I'm creating a browser multiplayer card game with React and Socket.IO. On the client, I have a clientController class which is responsible for connecting to the server, and communicating with it using Socket.IO. This is also where I define listeners for game events (like "start_game" or "new_round"). All these events are handled by listeners in a gameService file (which exports a single instance of a GameService class per client).
I'm using TypeScript and styled-components, but I don't think it is relevant for this question.
I have a GameRoom component (mainly for rendering, not much logic), but my plan was to manipulate most or all game state inside my GameService instance. This obviously means that my GameService instance would need to have access to the React Context I set up (for accessing and changing state everywhere), which it can't have because it is not a React component.
I tried defining variables in my GameService class for later declaration inside gameContext file, like so:
//inside GameService class
class GameService {
setGame;
...
}
export default new GameService();
//inside gameContext file
import gameService from "./gameService"
...
const [game, setGame] = useState<Game>();
gameService.setGame = setGame;
Even doing it this way, which avoids calling useContext() inside a file which has nothing to do with React components, it doesn't work.
For example, inside my "start_game" event listener (inside my GameService instance), I call this.setGame(new Game()) and it gives me a "this.setGame is not a function" error.
I think this has more issues than just the state setters, as the "game" state itself would probably just be converted to a normal variable.
Is there a way to effectively use state inside a non React component? Or should I turn my GameService class into a component that just handles logic? If so, where should I place it in my component hierarchy?

NestJs: dynamic module IoC scope

How does the framework manage the lifetime of DynamicModules?
The NestJs documentation on Modules states that:
In Nest, modules are singletons by default, and thus you can share the same instance of any provider between multiple modules effortlessly.
How can you share multiple dynamic module instances between modules?
The NestJs documentation on DynamicModules states that:
In fact, what our register() method will return is a DynamicModule. A dynamic module is nothing more than a module created at run-time, with the same exact properties as a static module, plus one additional property called module.
How can you manage/change the scope of DynamicModules? For example, changing them from behaving transitively to as a singleton. Defining their injection token, retrieving them on demand, etc.
How does the framework manage the lifetime of DynamicModules?
Generally speaking, like it does any other module. A dynamic module is just a special name for a module configuraed by a function and represented by an object. The end result is usually something like
{
module: SomeModuleClass,
imports: [Imports, For, The, Module],
providers: [SomeProviderToken, SomeProviderService, ExtraProvidersNeeded],
exports: [SomeProviderService],
}
Pretty much the same kind of thing you'd see in an #Module() decorator, but configured via a function that possibly uses DI instead of just written directly
How can you share multiple dynamic module instances between modules?
I might need a bit of clarification here, but I'll be happy to edit my answer with more detail once I know what's the goal here, or what you're trying to do.
How can you manage/change the scope of DynamicModules? For exmaple, changing them from behaving transitively to as a singleton. Defining their injection token, retrieving them on demand, etc.
The easiest option for sharing your configuration (besides making the module #Global()) is to make a wrapper module that re-exports the dynamic module once it has been configured.
Example: Let's say we have a dynamic FooModule that we want to pass application to, to designate the name of the application, and we want to re-use that module in several other places
#Module({
imports: [
FooModule.forRoot(
{ application: 'StackOverflow Dynamic Module Scope Question' }
)
],
exports: [FooModule],
})
export class FooWrapperModule {}
Now instead of importing FooModule.forRoot() again in multiple places, we just import FooWrapperModule and get the same instance of FooService with the configuration originally passed.
I do want to mention that by convention, DynamicModule.forRoot/Async() usually implies single time registration in the RootModule and usually has a #Global() or isGlobal: true config attached to it somewhere. This isn't always the case, but it holds relatively true.
DynamicModule.register/Async() on the other hand, usually means that we are configuring a dynamic module for this module only and it can be reconfigured elsewhere to have it's own separate config. This can lead to cool setups where you can have multiple JwtService instances that have different secret values for signing (like for an access and refresh token signing service).
Then there's DynamicModule.forFeature() which is like register in that it is at a per module basis, but usually it uses config from the forRoot/Async() call that was already made. The #nestjs/typeorm module, mikro-orm/nestjs module, and #ogma/nestjs-module module are three separate examples I can think of that follow this pattern. This is a great way to allow for general configuration at the root level (application name, database connection options, etc) and then allow for scoped configuration at the module level (what entities will be injected, logger context, etc)

What is the best way to organize the code of a nodejs-express project, using TypeScript?

While trying to organize the code of my first NodeJS-express project, I ran into some doubts about the use of namespaces, modules and classes. When to choose one? When another?
For example, my project is structured (simplifying) in.
routers -> controllers -> services -> repositories.
The possibilities I thought of to manage these "entities" are the following:
Classes
Classes with static methods
Singletons
Simple module export
Namespaces
Classes
I thought of avoiding them right away, since the above-mentioned entities do not need to memorize any state. Furthermore, they would complicate the code due to the need to be instantiated.
Classes with static methods
They are correct? Or rather a simple namespace or simple export of the modules?
Class + Singletons
A way of organizing the code in a "nicer" way than the simple class, but which does not convince me, since reading on the net that the singleton in TypeScript is replaceable with the namespace.
Simple module export
The way I thought to implement immediately, for example in this way (file user.repository.ts):
const add = async (user: User): Promise<void> => {
if(await canBeAdded(user)) {
//save user;
} else {
// throw error
}
}
export const UserRepository = {
add
}
It's corrects? Or am I not properly using what TypeScript offers? Being the first time I use this language, I would like to be sure I chose the right path.
Namespaces
Are they a better choice to develop the code published above? Are you advised against?
Thank you in advance for the answers! Any advice is welcome!
P.S. I know that, once the TypeScript is compiled, in Javascript the classes are practically syntactic sugar. What I'm interested in knowing are the best practices for writing good code in TypeScript.

Trying to understand IOC and binding

I am very new to concept of IOC and I understand the fact that they help us resolve different classes in different contexts. Your calling class will just interact with Interface and Interface with decide which implementation to give you and it takes care of newing up the object.
Please do correct me if I am understanding is wrong because my question is based on that:
Now, I see this pattern very often in these projects:
private readonly IEmailService emailService;
private readonly ITemplateRenderer templateRenderer;
private readonly IHtmlToTextTransformer htmlToTextTransformer;
public TemplateEmailService(IEmailService emailService,
ITemplateRenderer templateRenderer,
IHtmlToTextTransformer htmlToTextTransformer)
{
this.emailService = emailService;
this.htmlToTextTransformer = htmlToTextTransformer;
this.templateRenderer = templateRenderer;
}
I understand that this helps using all the implementations of these classes without newing them up and also you don't have to decide WHICH implementaion to get, your IOC decides it for you, right?
but when I code like this, I do not even touch any IOC congiguration files. And again I am usin git for 2 days only but from all the tutorials that I have read, I was expecting my self to configure something which says "Resolve IParent to Child" class. But it works without me doing anything like it. Is it because there is only one implementaion of these interfaces? and If I do have more than one implementations then and then only I will have to configure resolved explicitly?
The code sample you have is a case of Constructor Injection.
In a traditional code, you would have a parameterless constructor, and in it you would "new-up" your objects like this:
IEmailService emailService = new EmailService();
So your code is explictly controlling which implementation gets assigned to the interface variable.
In IoC using constructor injection, control is inverted, meaning the container is "driving the bus" and is creating your TemplateEmailService object. When it is about to create it, the container looks at your constructor parameters (IEmailService , ITemplateRenderer , etc.) and feeds those objects to your class for use.
The IoC container can be configured so that interface A gets fulfilled by implementation B (or C) explicitly. Each one has a way to do it. Or it could do it by convention (IFoo fulfilled by Foo), or even attributes in classes, whatever.
So to answer your question-- you can explicitly define which implementations get used to fulfill certain interfaces. Got to read the IoC container docs for how to.
One more thing - "when you code like this", you technically don't have to be using an IoC container. In fact, your class should not have a direct reference to the container - it will maximize the reusability, and also allow easy testing. So you would wire-up interfaces to implementation classes elsewhere.

Kohana helper attribute

I have a question that keeps bothering me. Currently, I have started using Kohana 3.2 Framework. I've written a helper to handle some functionality - I have a number of methods, which are (as it should be) declared STATIC. But, all of these methods are somehow working with the database, so I need to load a model. Currently, every method has a non-static variable like this:
$comment = new Model_Comments;
$comment->addComment("abc");
OK, it seems to be working, but then I wanted to get rid of this redundancy by using class attribute to hold the instance of the model (with is class as well).
Something like this:
private static $comment; // Declaring attribute
self::$comment = new Model_Comment; // This is done within helper __constuct method
self::$comment->addComment("abc"); // And call it within the method.
But, I got failed with: Call to a member function addComment() on a non-object
Question is: is it possible to do it ? Maybe there are some other approaches ?
Sorry for a long story and, thanks in advice! :P
A static method cannot call a non-static method without operating on an instance of the class. So, what you're proposing won't work. There may be a way do accomplish something similar, but what about trying the following:
You could implement the singleton or factory pattern for your "helper" class. Then, you could create the model (as an attribute) as you instantiate/return the instance. With an actual instance of your "helper" class, you won't have to worry about the static scope issues.
In other words, you can create a helper-like class as a "normal" class in your application that, upon creation, always has the necessary model available.
I'd be happy to help further if this approach makes sense.
David

Resources