I think you misunderstood the term helper function a bit. Helper function should not have reference to this as it indeed creates coupling. For sayHello to be uncoupled function it should look something like this:
const sayHello = (name) => ({ a: `${name} says hi!` });
// And later inside component:
this.setState(sayHello('snigo'));
This way logic is out of component and helper function is independent from the component at the same time
we need to have a specific contract defined between certain classes and helper function.
So the name of my state class is Compliance.tsx and name of helper file, which has these function is ComplianceStateHelper.ts Now there could be other class like ComplianceHistory.tsx and it might also use these helper functions from ComplianceStateHelper.ts
so contract has to definitely be defined. you actually are deep, I have to mention that I am kind of at fault for not giving all the details at once.
Functions in code base with free floating this is a massive code smell ā I will read more on this, for it will take me some time to learn on this.
but that pattern is how we use the compositional inheritance pattern
function FCat(name) {
this.name = `${name} + [FCat]`;
Object.assign(this, meower(this));
}
function meower(state) {
/** type 1 : setting property directly over the object
return {
...state,
meow() {
console.log(`${this.name} is meowing`);
},
};
*/
// type 2 : Better Approach, setting property on prototype of object
const proto = Object.getPrototypeOf(state);
proto.meow = function () {
console.log(`${this.name} is meowing`);
};
}
And this is the fragile part. You are making constraints on the class away from the class definition.
If a function is part of the class, it should be part of the class. If a function is not part of the class, then it should not obligate the class to have a specific internal representation.
so do you think itās ok to have classes with 500 lines of code what are the ways to make the files more readable
one way is inheritance, but that is again a bad pattern, I am inspired by Eric Elliot, which says, that OO is itself very fragile.
your explanation about making class and functions fragile, is acceptable, but what is the solution over making the code more readable?
when I say readable, I mean we want to keep cognitive overhead less while reading a file. That means, just like we know a function should do only one thing, I was expecting, that a file, should just explain one thing or only few things, making sure that line of code do not exceed 150 may be, that number i will have to research what is best and another thing can be explained by another file
I prefer to have everything related to one class or implementation in one file. I donāt see a big deal with larger files.
But I think thatās a separate question from how to implement composition without increasing cognitive overhead because you have hidden structural requirements for your class across a bunch of different functions.
yes, so basically, I have moved ahead from one class per file to many files for same class In the hope of reducing cognitive overhead, when reading one file related to that class
If it had to be done more properly may be creating a super class was the way to go forward. However I preferred compositional inheritance over here, over classical inheritance.
You can still do compositional inheritance without using this.. The two are unrelated.
Your implementation for a given method can be in a separate file and never use this.. The class calls the function with the arguments required, the function does its thing, and the class updates any internal data, as required, from the return value(s).
The function never sees or makes hidden requirements upon the internal representation of your objects and you loosen the coupling between components.
But why use the class connector? That is explicitly increasing the coupling between components. Why not directly call the external functions in the class methods, passing in the data required by the function signature?
In composition, your objects implement interfaces. The interfaces should clearly describe what they require and what they do. The interface should not mandate internal data representation in your objects. That violates encapsulation.
I am doing that only, I am calling an external function in class method,
classConnector is helping me curry it, itās returning me a new function, that gets state and setState by default and I will pass the data needed.
you have to see that actually we are delegating class logic outside. That is the where question revolves,
yes actually that is where we are discussing a pattern, because we have this.props and this .state
,
these are the only two thing we are managing,
and actually encapsulation may not come into picture, since we are not going out of a class, we just have a class and set of (composer+helper) function in contract with that React Class
But I have to agree that my OO knowledge is not good, because I started directly with JS, I will work on it
I donāt know how to phrase this so that it becomes clearer, but:
You are using a library that effectively allows you to write a UI as a series of functions. These functions return the result of a function call or tree of function calls (createElement calls, which is what JSX desugars to). These are then nested within other functions. So what you get is the representation of a DOM structure built from the reult of a nested set of function calls. A React codebase is effectively producing something like an S-expression
Now, under the hood, this is an object structure, but React handles the references to these objects internally. What you are doing is trying to layer an imperative OO abstraction over the top of the public API. It is unequivocally more complex, and is completely unecessary.
What should give you pause for thought that maybe you are not doing the right thing by discarding the idiomatic approach to writing React code is that at no point in the code you write do you use the classes to instantiate objects. This should be a hint to you that the class-based API is a convenience, that it isnāt being used like in an OO codebase. As I said in an earlier post, the function based API (that is decoming the de facto standard way of writing React code) is much closer, visually, to how the library works. Itās just functions, all the way down, very loosly coupled. Take some input (props) return some output. Keep it immutable as much possible. Donāt tie things together.
Edit: you mentioned Eric Elliot. Be a bit wary there. Iāve learned a few things from his writings, if you dig in he has a few useful things to teach. But heās also incredibly, aggressively self promotional and pushes for things that donāt quite seem correct a lot of the time. For example, pushing composition over inheritance (good), then presenting the One True Solution to thisā¦which looks suspiciously likeā¦inheritance. Take everything he says with a grain of salt, donāt blindly regurgitate his opinions. Many of them are contrary to common practice. This does not mean those opinions are wrong per se, but it is an indication they might not be as correct as he likes to state they are. Note that he tends to make up names for patterns, then write as if that name is the well known standard.
My argument wasnāt really about the naming but rather about your whole approach. You really should start from following:
Because nothing about this is correct and Iām starting to believe that this creates false belief framework for you.
You correctly said somewhere in this thread that React component ideally should do only one thing and this immediately creates at least two problems for you:
Classes are containers of functions mostly and thatās why using functions instead of classes in React is heavily suggested
And you want to go further by adding couple more functions from outside on top of it
React components are functions and youāre composing WITH these functions and NOT composing those functions.