I'd like to know the reasons to use Pinia over a javasript module with static members, I tried using both and I prefer the last one for this reasons:
Pinia don't let you make private functions / state, unless you make a weird aproach that is not even documented on the official documentation as far as I know, that involves returning manually functions/variables that you want to make accessible.
With an abstract class with static members you know all the time which are public and which are private, the code looks cleaner,
With Pinia you need to store the store in a variable in every template you use it like "let myStore = useMyStore()", instead with a module you can just access the property you need like "myModule.myProperty"
I know the pros of Pinia are the devtools plugin integration and also some extra functionality like $reset, and probably missing something, but still I dont find that enough so I'd like to know what do you think because it feels like there has to be something else that I'm missing. Thanks.
Related
Is there any advantages (or disadvantages) on using #NestJS/Config instead of using dotenv to retrieve envvar? In both cases I could create a class that is responsible for all envvars, but should I?
I know #NestJS/Config uses dotenv behind the curtains, but is there any reason why one should choose one over the other?
The two big advantages are the ability to use Joi or class-validator or whatever else you want as a schema validator to ensure you have your env values correct to begin with, before trying to access them at runtime and getting an error. Earlier feedback loop means fewer failures later on. The other big advantage is the use of DI meaning it's easier (usually) to mock the env variable value in your test cases, rather than having to assign to process.env itself. There's also slight speed improvements, as Nest caches the value so if you read it again you don't need to read from process.env, but other than that there's not too much to mention. If you don't want to use it, don't feel like you have to. There is also the disadvantage of not being able to use the ConfigService inside a decorator
My understanding is using #nestjs/config is easy for you to manage your config/envvars as a module in your project. So it can be easily swapped in different place:
e.g. if you need a different set of config for test, you don't have to actually modify your process.env.xxx or use a different .env file.
However if you do that, it requires all/most your other services to utilize this pattern as well. It wouldn't be so helpful if you have all your other service to be a pure function export.
In front-end apps there is often data which needs to be accessed by many components. Routing is one example, another is configuration data, e.g. feature switches, default language, etc.
In an app that isn't using any particular framework, I might share this configuration data across modules using
export class Configuration {
static getConfig () {
// get the config from the server
return axios.get('/config').then(function (response) {
return response;
})
}
}
Then import this class into any module that needs to access configuration data. With some front-end framework, it's obvious how to share such "global" data, e.g.
AngularJS - Configuration should be defined as a service that's dependency-injected into any controllers/directives/services that need to access config. data
Vue.js - use a mixin
However, when using ReactJS it's not obvious which approach should be used. Possible options are:
A plain-old JavaScript module. Encapsulate the data to be shared as a function/method, and import it into any React components that need to access it. The seems like the simplest approach, but I have the feeling that when writing a ReactJS app everything should be defined as a component, rather than JavaScript classes/functions.
Redux seems to be recommended approach for sharing-state within large apps, but this feels like overkill for smaller projects
Something else?
but I have the feeling that when writing a ReactJS app everything
should be defined as a component, rather than JavaScript
classes/functions.
I really don't see a reason why everything should be a component in React. If it is just data, you can create a single instance of that JS object say and import that anywhere you need it.
I have used similar thing in my app, where I had a "global" kind of object which was saving different configs etc, and then I was using that in the components which needed that data.
Here is also some more info about component communication in React.
A plain-old JavaScript module. Encapsulate the data to be shared as a function/method, and import it into any React components that need
to access it. The seems like the simplest approach, but I have the
feeling that when writing a ReactJS app everything should be defined
as a component, rather than JavaScript classes/functions.
I disagree, React is a library that helps to create user interfaces through components but it doesn't mean that (services, translations, configuration data) have to be built into components, on the other hand, it's actually discouraged you shouldn't couple your services/configuration to a library
you should limit the scope of React to what it is used for. So using plain-old JavaScript modules feels the right way to implement a simple react app.
Redux seems to be recommended approach for sharing-state within large
apps, but this feels like overkill for smaller projects
I think it depends on the complexity of the app rather the size, here is where you should think on, how does your app will evolve or if redux isn't what you really need to remove all this data-sharing dependency within React.
Something else?
The react context (discourage)
The observable pattern
https://www.npmjs.com/package/react-observable-subscribe
I think you should go for the redux solution. It sounds like an over kill but it has an added advantage of having a global state object, therefore you can easily choose when to re-render your app when data is shared across compoents.
you can use context in react :
https://reactjs.org/docs/context.html
or you can create a global variable in window object too
the other way is to use observer design pattern plagin and use it.
mobX or other stateManagement component is good too beside redux
Following a rapid-prototyping approach, I am developing an application in Marionette.js/backbone.js and heavily used the window-object to bind collections and views to the global stack (e.g. window.app.data, window.app.views).
Of course, it is always better (smoother!) to encapsulate objects in a single class and pass them as parameters where needed. However, this has some limitations when an app and its potential use-cases become really big. And as the data I deal with comes from an API and therefore would be anyway accessible to anybody interested, does that justify storing data in the window-object? Or are there other best-practices in ES6 (or especially Marionette.js) to achieve the same results, but in a more private manner?!
I already go into details about a simple namespacing pattern in JavaScript in another answer. You seem to be already close to this with window.app.data etc.
But it looks like you have a lot of misconceptions about how JavaScript works.
a namespace-based solution that integrates nicely with Browserify/AMD-modules
Then why not use RequireJS? Browserify? or Webpack? There's nothing that a global ridden spaghetti code can do that a modular approach can't do better.
such would be read-only
No. While not impossible to set an object property to read-only, you must explicitly do it with something like Object.seal or Object.freeze.
I do not want to attach objects to the namespace, but actual instances
JavaScript do not have "namespaces" as part of the language, it's just a pattern to scope all your code within literal objects (key-value).
You can put whatever you'd like.
const MyNamespace = {
MyType: Backbone.Model.extend({ /*...*/ }),
instance: new Backbone.Model(),
anyValue: "some important string",
};
Ideally, you would define the namespace within an IIFE to avoid leaking any variable to the global scope.
const app = app || {};
app.MyModel = (function(app){
return Backbone.Model.extend({
// ...
});
})(app);
[...] data I deal with comes from an API and therefore would be anyway accessible to anybody interested
Even if the data is contained within a module that do not leak to the global scope, anybody can access the data. That's how JavaScript works, it's in the user's browser, he can do whatever he wants with the code and the data.
does that justify storing data in the window-object?
No.
Or are there other best-practices in ES6
ES6 has nothing to do with the architecture and patterns you take for your app.
but in a more private manner?!
Like I said earlier, privacy in JavaScript can't be expected.
[encapsulate objects in a single class and pass them as parameters where needed] has some limitations when an app and its potential use-cases become really big.
That's just incorrect. It's the other way around. Software patterns exist solely to help alleviate any limitations that arise as a project grows in scope.
There are multiple patterns you can use that will help deal with the complexity of a bigger app, like:
Modular approach with components
Dependency injection
Service containers
Factories
Events
etc.
I didn't read specifically this book, but JavaScript Design Patterns seems to be a good way to learn more and it demonstrates specific implementations of software patterns in JS.
I kind of understand how change detection works in Angular 2 but I'm really struggling to transfer/change my AngularJS methods over to NG2 regarding change detection.
Imagine I have a component that takes a single #Input() anObject and has a single function, logAllProperties() which, for arguments sake, logs all the properties to the console.
All I want to do is to call logAllProperties() every time anObject changes in anyway whatsoever.
I understand that treating the object as immutable (either with an external library like Immutable.js or by enforcing that the entire object changes even for a minor property change) will trigger ngOnChange but is there anyway to call a function whenever a change takes place aside from these or using DoCheck which I understand is potentially extremely inefficient.
As well as "is there a way", what is the correct way to do something like this? I'm new to Angular2 so I'm more than happy to learn the right way if Immutable and Observables are the way to go.
Thanks in advance
The straightforward way of executing an action everytime anObject change is by using a setter or ngOnChange (see Fals' answer).
Using immutable objects witch a change detection strategy of OnPush is a way to improve change detection performance. This is not the most obvious use of change detection in Angular.
For a complete explanation I suggest you read this really good article and if you have some time (45 minutes) you can check this video by the author of the article here
From there, you should have a good understanding of what's going on.
#input decorator is denoted your component is expecting to get some data from its parent which will be caught at that property
same way #output is the decorator in angular2 wherein parent component you can catch something from child.
Internally it uses observable and I don't think it's immutable.
ngrx provides a redux type immutable mechanism where every state is remembered and you can go back to them as well.
Observable and ngrx are running in parallel now.
I found out in our projects that using set works well in some cases, but others cases that need sync between components could be troubling, then we are using ngOnChange for those cases. Here's an example.
#Input() set myProperty(myProperty: MyPropertyType) {
if (myProperty) {
this.logService.log(myProperty);
}
this._myProperty = myProperty;
}
private _myProperty: MyPropertyType= new MyPropertyType();
The thing about Angular2 new lifecycle still confuse, and the documentation samples doesn't fit most of the real world cases.
Let's imagine, in a OO world, I want to build a Torrent object which listens to the network and lets me interact with it. It would inherit an EventEmitter and would look something like this:
var torrent = new Torrent(opts)
torrent.on('ready', cb) // add torrent to the UI
torrent.on('metadata', cb) // update data in the UI
and I can also make it do things:
torrent.stop()
torrent.resume()
Then of course if I want to do delete the torrent from memory I can call torrent.destroy().
The cool thing about this OO approach is that I can easily package this functionality in its own npm module, test the hell out of, and give users a nice clean reusable API.
My question is, how do I achieve this with Cycle.js apps?
If I create a driver it's unclear how I would go about creating many torrents and having their own independent listeners. Also consider I'd like to package functionality in a way that others get to easily reuse it in other Cycle.js apps.
It seems to me that you are trying to solve a problem thinking about it as you would write "imperative code".
I think creating Torrent instances with their own listeners is not something you should be using in cycle components.
I would go about it differently - creating Torrent module and figuring out what would be its sources and sinks. If this module should be reusable and published, you can create it as a function that would receive streams as arguments. Maybe something similar to TodoMVC Task component (which is then used in its parent component).
Since this module can be created as a pure function, testing it should be at least just as easy.
This implementation of course depends on your requirements but communication with the module would then be done only with streams and since it would be declarative there would be no need for methods like stop() and destroyed() which you would call from elsewhere.
How do I test it?
In cycle.js you'd write a component with intent model and view functions.
You'd test intent(), for given input Streams, produces Streams of actions that you want. For models, you'd test that given http and action streams, you get the state you want, and for view, you test that given a state you get the VDom you want.
One tricky bit with cycle.js is that since it passes functions around, normal JavaScript objects that use the 'this' keyword are not worth the trouble due to 'this' context problems. If you are working with cycle.js and you think you might write a JS class for use with Isolate, Onionify, or Collections most likely, you are going in the wrong direction. See MDN docs about 'this'
how I would go about creating many torrents
The Cycle.js people have several ways to deal with groups of things like this.
This ticket describes some things that might work for that:
Wrap subapp in Web Component
Stanga and similars.
Cycle Collections
Cycle Onionify