ES6 React - static method vs constructor - javascript

I'm running into an "issue" where I don't know which one is the best option.
Say I have the following class
export default class A {
constructor(){
this.testMethod = function testMethod(){
console.log('a')
}
}
static testMethod2 = function() {
console.log('B')
}
}
now I'm extending this class
class C extends A {
fetch() {
this.testMethod()
A.testMethod2()
}
}
Defining it as a static method feels weird to use when extending it, I would assume the fact that I'm extending a class would allow me to access all of its own methods (ES5 prototype style)
I know both ways are correct but what's the best way to do this in ES6/React ? What are some caveats of both ways or performance issues ?
I'm currently using the constructor because it feels like the right/intended way of doing it but I can't "justify" one over the other.
All this came from applying the airbnb eslint to my code base (http://eslint.org/docs/rules/class-methods-use-this)

I would assume the fact that I'm extending a class would allow me to access all of its own methods
You actually can do that. Just call C.testMethod2() instead of A.testMethod2() (or even use this.constructor.testMethod2()).
Defining functions that have nothing to do with a particular instance on the prototype or even inside the constructor is a bad practise, don't do that.

Related

Is the static method of javascript or typescript class also released by the garbage collector?

When implementing a method used only within a specific component class, it can be declared as a static method and an instance method, and I wonder the difference between the two.
Declaring methods of classes used across applications, such as the Util class, static is common, but I wonder if it is the right way to declare static just because it does not refer to this within a particular component class.
According to my research, the static method of class is disadvantageous in terms of memory because the memory remains intact even if the component's life cycle ends. If so, isn't it more advantageous to use it as an instance method even if it's only used within a specific class and not referenced to this?
class MyComponent {
// ex1) instance method
private isValidInput(text) {
return !!text.trim()
}
// ex1) static method
private static isValidInput(text) {
return !!text.trim()
}
}
When implementing component classes using Angular, I wondered if I would implement util functions that are only used in specific component classes as static or instance methods.

How to mock set state and method from protected abstracts method in React Jest

This is how the components are arranged
class A extends React.Component {
state = {mode: 'create'}
abstract getRows() {
}
abstract getTitle(){
}
}
class B extends A {
getTitle(){
if(this.state.mode === 'create'){ return 'New';}
else {return 'Existing'};
}
}
And in test case:
jest.mock('componentAFile');
component = shallow(<B />);
component.setState({mode: 'create'});
expect(component.instance().getTitle()).toBe('New');
component.setState({mode: 'edit'});
expect(component.instance().getTitle()).toBe('Existing');
But state mode says undefined. What is the correct way to do this? How do we test such classes inheriting from base classes?
First, better don't use that inheritance approach. Composition is so many way better that I even cannot recall any cons of inheritance.
Second, using .setState you are literally accessing internal aka private data. Or in other words "implementation details". There are so many cases when it breaks suddenly(renamed property in this.state, refactored class component into function, decompose one component into several etc etc), that there are no reason to use it.
Third, the same is with testing internal methods. Again, it's implementation details, for both name, arguments ordering, result returned. And moreover, let's assume you never use that function in what component renders in render(). So test will pass, but component might be broken.
What can you do instead?
Provide prop(shallow(<B prop1={mockedValue} prop2={anotherValue} />);)
change prop(.setProps)
call callback(component.find('button').simulate('click'))
validate against rendering results: expect(component.find('.title').text()).toBe('New')
also we may want to validate whether some mocked external service/utility has been called(but your case probably does not need that; just want to have complete list)

Mixins as utility library in Polymer 2.0

I am working in web application project which is made in Polymer 2.0, All Custom elements extends some Mixins. Some of those Mixins just provide utility functions to custom elements just like Date Time Utility functions or any Math related functions. My question is whether to use mixins & extends them to custom elements or just wrap them in plain java-script file and load that java-script file on index.html or entry point of application and use as global scope just like we use lodashjs or underscore.js.
The problem i find with Mixins is it always get applied to prototype chain of each custom element class object, So i end up those same utility methods with each custom element of my application.
Please suggest me best approach for Utilities in Polymer related apps.
That is a rather tough question to answer properly... as the real answer is just "both are valid solutions - it depends on your use case". Which I guess is not helping too much. So let's give you some context.
For real utilities, it is probably best to put them in a class as a static function.
class MathHelper {
static addOne(value) {
return value + 1;
}
}
class ElOne extends HTMLElement {
connectedCallback() {
this.innerHTML = `5 + 1 = ${MathHelper.addOne(5)}`;
}
}
customElements.define('el-one', ElOne);
<el-one></el-one>
Mixins, on the other hand, can serve a similar need but should be more "connected" to the Element they are used on.
(Sorry for the terrible example but from the top of my head I could not come up with something better)
const MathMixin = superclass => class extends superclass {
addOneTo(prop) {
this[prop] += 1;
}
}
class ElTwo extends MathMixin(HTMLElement) {
constructor() {
super();
this.number = 5;
}
connectedCallback() {
this.addOneTo('number');
this.innerHTML = `5 + 1 = ${this.number}`;
}
}
customElements.define('el-two', ElTwo);
<el-two></el-two>
Conclusion:
Class:
if possible use it
maybe even use static functions
it's easier to test and to maintain
Mixin:
if you need to enhance another class e.g. to allow
myElemenet.changeLanguage('de'), ...
if you need any other state of the class
I hope this clears it up at least a bit. If you have more concrete examples what needs to be implemented we could propose a recommended way of implementation.

Bulk binding class methods in react

I was looking for a way to bind react class methods to this in the constructor all at once, because I got tired of typing this._anotherFunction = this._anotherFunction.bind(this) 10 times for each component.
I haven't seen anyone else posting solutions for this and thought it would be useful to share my answer.
Interested to see if anyone else has similar implementations, or if there are any issues with the way I implemented.
Given the following React class functions:
_showModal() {}
_hideModal() {}
// etc.
In the constructor I added:
// bind all of the class's methods to the class
bindClassMethods.bind(this)([
'_showModal',
'_hideModal',
// etc.
]);
Here's the re-usable util function I wrote to pull this off:
export function bindClassMethods(classMethods = []) {
if (!_.isArray(classMethods)) {
console.error(`Need to pass an array to bindClassMethods().`);
return;
}
classMethods.map(fnc => {
if (!this[fnc]) {
console.error(
`Warning: func ${fnc} is not defined! It probably has been removed from this class' methods.`
);
} else {
this[fnc] = this[fnc].bind(this);
}
});
}
I found the console logs useful for reminding myself when I forgot to remove or update a function binding.
Revisiting this issue - the previous suggestion to use arrow functions as class properties have some drawbacks, including performance implications. (Albeit an arguably negligible performance implication, but one worth noting).
New Proposed Solution:
create a new class that extends Component, e.g. ComponentAutoBind
any sub-component that extends ComponentAutoBind will automatically have its own methods bound to the class instance
exclude React lifecycle methods from binding
See this gist for proposed solution
Working codepen example
I realize that extending Component may not be best practice but my implementation is only affecting the constructor - all other Component class properties are untouched.
Here are some links for the unconvinced:
https://medium.com/#forsakenharmony/you-should-maybe-mention-that-the-arrow-function-in-the-class-body-is-just-syntactic-sugar-c7bfb3383bef
https://blog.usejournal.com/arrow-functions-are-disrupting-react-components-63662d35f97b
https://medium.freecodecamp.org/why-arrow-functions-and-bind-in-reacts-render-are-problematic-f1c08b060e36 - only discusses Render method but same principle applies to class properties

understanding es6 mixin superclass convention

I created my own es6 mixin (and it works, yea!). However, it seems that I do not fully understand what I have created here (following example here):
export var EventEmitterMixin = (daSuperClass) => class extends daSuperClass {
}
How do I read this line of code? It seems that daSuperClass is just cruft (as I can evidently change it to anything I like)? Why is it in there two times?
When defining a function you need to give a name to your parameters so that you can reference them. It may be easier to see what's going on if it is rewritten without the fat-arrow syntax:
export var EventEmitterMixin = function(daSuperClass) {
return class extends daSuperClass {
[...]
}
}
So the argument your mixin takes is going to form the prototype for the new class you are creating. You mix in your extra functionality by 'extending' from the base class you provide.

Categories