I've been using Vuex, and it's adherence to only altering state through it's mutators or actions makes me think your store should only include as flat an object as you can, with only primitives types.
Some threads even prescribe normalising your data (so instead of nested object trees you have objects with arrays of id's to indicate tree relationships). This probably matches closely to your JSON api.
This makes me think that storing classes (that may have methods to alter themselves) in your flux store is an anti-pattern. Indeed even hydrating your store's data into a class seems like you're moving against the tide unless your class performs no modifications to its internal data.
Which then got me thinking, is using any class in a Vue/Vuex/Reactive/Flux an anti-pattern?
The libraries seem explicitly designed to work with plain JS objects and the general interactions you have with the API (data in, data out) makes me feel like a more functional approach (sans immutability) is what the original designers were thinking about.
It also seems be easier to write code that runs from function => test => state mutator wrapper around function.
I understand that JS objects and JS classes behave very similarly (and are basically the same thing), but my logic is if you don't design with classes in mind, then you're more likely to not pollute your state with non-flux state changes.
Is there a general consensus in the community that your flux code should be more functional and less object orientated?
Yes. You are absolutely right in what you are thinking. State containers like Redux, Vuex are supposed to hold your data constructs and not functions. It is true that functions in JavaScript are simply objects which are callable. You can store static data on functions too. But that still doesn't qualify as pure data. It is also for this same reason that we don't put Symbols in our state containers.
Coming back to the ES classes, as long as you are using classes as POJO i.e. only to store data then you are free to use those. But why have classes if you can have simple plain objects.
Separating data from UI components and moving it into state containers has fundamental roots in functional programming. Most of the strict functional languages like Haskell, Elm, OCaml or even Elixir/Erlang work this way. This provides strong reasoning about your data flows in your application. Additionally, this is complemented by the fact that, in these languages, data is immutable. And, thus there is no place for stateful Class like construct.
With JavaScript since things are inherently mutable, the boundaries are a bit blur and it is hard to define good practices.
Finally, as a community, there is no definite consensus about using the functional way, but it seems that the community is heading towards more functional, stateless component approaches. Some of the great examples are:
Elm
ReasonML
Hybrids
swiss-element
Cycle.js
And now, even we have functional components in both Vue and React.
First of all: This is not an question of opinion (I'm afraid someone will flag this question), I'm interested in the technological background or the decisions for this.
That being said: Redux's store needs to be serializable. It is not allowed or frowned upon to use model classes and write their instances in the store. This is highly annoying to me. The applications logic ends up in actions or reducers where models would be a nice thing to have.
I am wondering why. What is the technological decision behind this? Why not write class instances to the store?
1) Class in instances are mutable, which leads to the same problems redux has tried to address around predictability of state by championing immutability. It also means you have to do more manual shouldComponentUpdate checks for changes if pairing with React (as references to mutated instances will be the same even if their internal state has changed)
2) Immutability makes it possible to move back and forth between states (eg during time travel debugging), something that cannot be done when mutations have occurred within instances
3) Serialisation means its very easy to persist and rehydrate the store (to/from JSON) for more advanced uses such as server side rendering and offline use
If you are interested I just wrote a more in depth answer to a similar question with an example of how it is possible to use the best of both worlds https://stackoverflow.com/a/47472724/7385246
I've been using object-oriented programming practices for 25 years and trying to move toward functional programming for the last 5 years, but my mind always goes towards OOP when I'm trying to do something complex and, especially now that ES6 supports decent OOP syntax, that's the natural way for me to build stuff.
I'm now learning Redux and I understand (c.f. How to put methods onto the objects in Redux state?) that it's a no-no to put class instances in your reducers; and the recommended method for computing on top of plain reducer state is by using selectors (e.g., via reselect). And, of course, React recommends composition over inheritance (https://facebook.github.io/react/docs/composition-vs-inheritance.html, React redux oop classes).
But is there any place in the React/Redux ecosystem for class objects with methods and inheritance?
I guess, to sort of answer my own question, OOP classes encourage the addition of data properties and operations on the data in the same place, which is nice for readability, but doesn't fit well with pure functions and immutable data.
If I was going to use OOP, would I need to chuck the idea of having my instances persist and maintain state for any amount of time? Like, every time I want to use one, I would instantiate it from store data, use whatever methods I want, and throw it away? That might obviate a lot of the impetus to use OOP classes. But if I keep instances around, I'll have headaches keeping them synced with the store.
So, is the answer to always use selectors when I'm tempted to use methods and always use composition when I'm tempted to use inheritance? Specifically, I mean when storing and manipulating data held in a Redux store for use in React components. And, if so, where should it fit in? Connected to selectors? Immediately disposable like I suggested?
Adding my use case for clarity: My data is basically a huge graph: lots of objects with lots of properties and lots of relationships between objects. It's read only, but complex. My objects are called "concepts".
Before making the (probably foolish) decision to migrate to Redux, I used classes to structure and represent concepts, sets of concepts, and relationships between concepts. My classes included async api logic to fetch concept sets, information about each concept, and information about other concepts that each concept is related to. If the user chose to drill down, the classes would recursively fetch and instantiate new concept sets. The Redux documentation recommends flat, normalized structures for nested data (http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html) which is probably wise for storage, but my OOP model was good for traversing sections of the graph and stuff. I have a hard time wrapping my head around using selectors and immutable state that might involve nesting, potentially with cycles, or needing to make async calls for more data.
I'm successfully using https://redux-observable.js.org/ for the api stuff.
Maybe #Sulthan's answer is right: I should feel free to use OOP techniques in my Redux application. But it still seems weird. I can't keep my objects around because if the store changes (more data is fetched, for instance), my objects can get stale. If my objects are nested but my store is normalized, I'll instantiate them (from selectors) when I need them and make sure not to keep them around...
The answer is that it's possible but heavily discouraged and non-idiomatic.
React does rely on classes and single-level inheritance of React.Component to implement stateful components with lifecycles, but you are officially discouraged from doing further levels of inheritance in components.
Redux is built around Functional Programming principles. For a variety of reasons, you are encouraged to keep your state as plain JS objects and arrays, and access/manipulate it using plain functions.
I've certainly seen many libraries that tried to add an OOP layer on top of Redux (such as classes whose methods are turned into action creators and reducers). Those work, but are definitely going against the overall spirit of Redux.
I do actually use a library called Redux-ORM, which does allow you to define Model classes that act as a facade over the plain JS objects in your store. However, unlike many of the other libraries that I've seen, it works with Redux rather than trying to change how Redux behaves. I discussed how Redux-ORM works, how I use it, and why it's still reasonably idiomatic, in my blog posts Practical Redux, Part 1: Redux-ORM Basics and Practical Redux, Part 2: Redux-ORM Concepts and Techniques. Overall, it's an excellent tool for helping manage relationships and normalized data in your Redux store.
Finally, I'm currently working on a blog post that will discuss the actual technical limitations that Redux requires (and why), vs how you are intended to use Redux, vs how it's possible to use Redux. I hope to have that up in the next week or so - keep an eye on http://blog.isquaredsoftware.com .
I'll answer my own question by describing what I ended up doing, imperfect as it is.
First, instead of regular ES6 class syntax, I've started using stampit, which is uglier that ES6 classes, but much more flexible.
Mainly, though, my complex objects exist in two forms:
plain JS objects for the store
class (actually stamped) instances for convenience and power of using instance methods.
I use a convention of putting an _underscore in front of all references to the plain objects. My "solution" is kludgy and bad for lots of reasons, but I think trying to use selectors for everything would be worse. If you're curious, here's the place in my code where I "inflate" my plain store objects into instances: https://github.com/Sigfried/vocab-pop/blob/localstorage/src/ducks/conceptSet.js#L292
UPDATE
Turning redux state POJOs into class instances (regular or stampit) is a terrible idea and someone should have stopped me long ago.
I probably should have accepted #markerikson's answer, and maybe the Redux-ORM thing is worth looking at, but I just wanted to say definitively, DON'T DO WHAT I DID. (I always think I'm so smart filling in the "gaps" of technologies I'm learning with clever hacks -- and then I spend painful months cleaning up the mess once I understand why that technology didn't include my hack in the first place.)
Another update
From Composing Software: An Introduction:
What we won’t do is say that functional programming is better than
object-oriented programming, or that you must choose one over the
other. OOP vs FP is a false dichotomy. Every real Javascript
application I’ve seen in recent years mixes FP and OOP extensively.
Looks like there are good ways to think about combining FP and OOP, and it will, no doubt, use some immutable classes and composition without a lot of inheritance. This series on composition looks like what I needed to learn.
This question is a bit opinion-based but let's concentrate on the core points.
There is no contradiction between functional programming and OOP. You just need to use the same programming patterns. There is no problem to use classes (with inheritance) in functional programming, if you keep them immutable.
To prove my point, the popular library Immutable.js that is used by many people to keep state in redux is composed from classes. And those classes have inheritance (e.g. OrderedSet extends Set).
Also note that most React components are classes and they use inheritance, too (... extends React.Component).
I come from an OOP background and I'm learning Redux. It seems the more I learn about Redux, I realize how it contrasts with the OOP paradigm by employing more functional constructs.
That said, I've never used Backbone, but I came across this in the redux docs regarding migrating from Backbone models:
Backbone's model layer is quite different from Redux, so we don't suggest mixing them. If possible, it is best that you rewrite your app's model layer from scratch instead of connecting Backbone to Redux...
Source:
https://github.com/reactjs/redux/blob/master/docs/recipes/MigratingToRedux.md#from-backbone
Moreover, I found that initially, this simply read:
Sorry, you’ll need to rewrite your model layer.
It’s way too different!
Source: https://github.com/reactjs/redux/commit/fbe0852a25d4bf9819adfe95fef6aa6702658c07#diff-a7be1d864910aa327225143859006953R30
Sooo... Is Dan saying to rewrite you model layer because models, (such as those from Backbone) are OO in nature and redux prescribes to a more functional paradigm?
Yes and no. You need to rewrite your data stuff to not be models but POJOs in the state. They can look a lot like models and they are definitely objects, but they can't have methods. Well, technically they could and it may not even be a problem, but it's discouraged because the state ought to be serializable.
Because I like setting properties and calling methods more than I like dispatching actions, and because I like to attach my code to my data, I wrote a library that lets you use models instead of the standard Redux action creator/action/dispatch/reducer paradigm. Under the hood, it's 100% Redux, but the Dev API is all OOP. This way it has all of Redux's benefits and all OOP's benefits. You may find it alleviates some of the concerns you voiced.
But you still have to rewrite your model layer.
I encounter a situation where component A needs to know about the state of component B when A is asked to perform certain actions (for example, if edit menu is toggled, the save action on the save button should not be performed). My application is structured like a tree with nested components.
I have tried passing all the components I need into the constructor of other components. I find this quite tedious whenever I add more component to the application, I have to pass them all the way down. Furthermore, some components are instantiated under the same constructor, but they need to know about each other. I cannot pass say component A and B into each other since I need to instantiate them in order.
I have also tried using event system to signal between components. (Observer pattern ?) It seems to be more of an overkill and not intended to be used like this.
3rd thing I try is to use singleton through dependency injection. Components register themselves on init to the provider and the provider can be injected to provide access to other components.
The 3rd approach is the most effortless and it is working for me. But I google that Singleton is not a recommended approach since it is just global variable and it entangles the code. But Unity game engine seems to have the same thing ( FindComponentByTag ). What is the general practice for this ?
The standard pattern for handling things like this is MVC (Model View Controller) which usually makes use of the Observer pattern. Components (I guess that you are having GUI components in mind) should not directly access the state of other components. Instead, state should be handled by the model. The components that need to know about the state are registered as observers of the model.