The documentation around Microsoft's recently released ReactXP doesn't have much information about the RX.Component class at the moment.
Here's an example from the documentation:
class HelloWorld extends RX.Component<void, void> {
render() {
return <RX.Text>Hello World</RX.Text>;
}
}
What are the features offered by RX.Component over React.Component?
How does it influence the life-cycle of the base Component class?
This is an important consideration for me because best practices for React components typically encourage composition over inheritance, except for very basic scenarios like PureComponent. Would the features provided by RX.Component justify the inheritance?
I believe it's the same:
https://github.com/Microsoft/reactxp/blob/master/src/web/ReactXP.ts#L131
Maybe they just want to make everything under the RX namespace so you only need to import RX = require('reactxp');
Related
I have a typical Glimmer "base" component:
import Component from '#glimmer/component';
export default class BaseComponent extends Component { ... }
It has a template like normally, but the actual implementations of that component are child componenents, that override some of the template getters and parameters so that it works with various different data types.
export default class TypeAComponent extends BaseComponent { ... }
export default class TypeBComponent extends BaseComponent { ... }
etc.
My question is: How do I specify that all the child components should use the parent class template, so I don't have to duplicate the same fairly complex HTML for all child components? Visually the components are supposed to look identical so any changes would have to be replicated across all child component types. Therefore multiple duplicated templates isn't ideal.
In Ember Classic components there was layout and layoutName properties so I could just do:
layoutName: 'components/component-name'
in the base component and all child components did automatically use the defined template.
Now that I'm migrating to Glimmer components I can't seem to figure out how to do this. I have tried:
layout property
layoutName property
template property
Using the child components without a template in hope that they would automatically fall back to the parent class template.
Only thing that seems to work is creating Application Initializer like this:
app.register('template:components/child1-component', app.lookup('template:components/base-component'));
app.register('template:components/child2-component', app.lookup('template:components/base-component'));
But that feels so hacky that I decided to ask here first if there is a proper way to do this that I have missed?
How to specify template for Glimmer Component?
tl;dr: you should avoid this.
There are two answers to two, more specific, questions:
What is the recommended way to manage complex components with shared behaviors?
Typically, you'll want to re-work your code to use either composition or a service.
Composition
<BaseBehaviors as |myAPI|>
<TypeAComponent #foo={{myAPI.foo}} #bar={{myAPI.bar}} />
<BaseBehaviors>
Where BaseBehaviors' template is:
{{yield (hash
foo=whateverThisDoes
bar=whateverThisBarDoes
)}}
Service
export default class TypeAComponent extends Component {
#service base;
}
and the service can be created with
ember g service base
then, instead of accessing everything on this, you'd access everything on this.base
Ignoring all advice, how do I technically do the thing?
Co-located components (js + hbs as separate files), are combined into one file at build time, which works like this:
// app/components/my-component.js
import Component from '#glimmer/component';
export default class MyComponent extends Cmoponent {
// ..
}
{{! app/components/my-component.hbs }}
<div>{{yield}}</div>
The above js and hbs file becomes the following single file:
// app/components/my-component.js
import Component from '#glimmer/component';
import { hbs } from 'ember-cli-htmlbars';
import { setComponentTemplate } from '#ember/component';
export default class MyComponent extends Cmoponent {
// ..
}
setComponentTemplate(hbs`{{! app/components/my-component.hbs }}
<div>{{yield}}</div>
`, MyComponent);
So this means you can use setComponentTemplate anywhere at the module level, to assign a template to a backing class.
Why is this not recommended over the other approaches?
All of this is a main reason the layout and related properties did not make it in to Octane.
Formally supported Component inheritance results in people getting "clever"
this in of itself, isn't so much of a problem, as it is what people can do with the tool. Bad inheritance is the main reason folks don't like classes at all -- and why functional programming has been on the rise -- which is warranted! Definitely a bit of an over-correction, as the best code uses both FP and OP, when appropriate, and doesn't get dogmatic about this stuff.
Component Inheritance is harder to debug
Things that are a "Foo" but are a subclass of "Foo" may not actually work like "Foo", because in JS, there aren't strict rules around inheritance, so you can override getters, methods, etc, and have them provide entirely different behavior.
This confuses someone who is looking to debug your code.
Additionally, as someone is trying to do that debugging, they'll need to have more files open to try to under stand the bigger picture, which increases cognitive load.
Component inheritance allows folks to ignore boundaries
This makes unit testing harder -- components are only tested as "black boxes" / something you can't see in to -- you test the inputs and outputs, and nothing in between.
If you do want to test the in-between, you need to extract either regular functions or a service (or more rendering tests on the specific things).
I would say this is the classic case for a composition, where TypeAComponent and TypeBComponent use the BaseComponent.
So you have your BaseComponent with all the HTML, that basically is your template. I think its important here to think a bit more of Components also as possible Templates, not only full Components. So lets call this the TemplateComponent.
So you have your TemplateComponent which could also be a template-only component. Then you have as template for TypeAComponent and TypeBComponent:
<TemplateComponent
#type={{#title}}
#title={{#title}}
#onchange={{#onchange}}
#propertyThatIsChanged={{this.propertyThatIsChanged}}
...
/>
this allows you to have a getter propertyThatIsChanged to overwrite pieces. Common behaviour can also be placed on the TemplateComponent, or, if its common code, maybe on a BaseCodeComponent, that only contains shared code, while I would rather not do this.
For areas you want to replace this also opens the possibility to use Blocks.
The TemplateComponent, for example, could use has-block to check if a :title exists, use this block then ({{yield to="default"}}), and if not just use {{#title}}.
So, to the only obvious downside of this: you have to proxy all params. This seems ugly at first, but generally I think its better for components not to have too many arguments. At some point an options or data argument could be better, also because it can be built with js when necessary. It should also be mentioned that there is an open RFC that would address this issue. With the upcoming SFCs, I think this is the much more future-proof solution overall.
I've observed a way we import and extending in react. The way I usually write is as following.
import React from 'react';
class SomeClass extends React.Component {
//Some code
}
but I've seen people using the following way as well.
import React, { Component } from 'react'
class SomeClass extends Component {
//Some code
}
What is the best way or the best practice when writing the imports. is it the 1st way or the 2nd way? or is there any other way as the best practice. Please advice.
There is no best practice for this particular case. Both snippets do exactly the same thing. As #Rajesh said, it's only a matter of opinion and personal preference.
Personally, I prefer approach 1 because we have already imported React which is where Component is under. Also, I think extends React.Component vs extends Component makes little difference to the eye.
That being said, if you are exporting multiple React components from the same file, it makes more sense to use approach 2, as that would shorten your code a bit.
One example where case two is useful is say you have a module that exports multiple hard-coded constants or helper functions
Such as
types.js:
export const ACTION_1 = "...";
export const ACTION_2 = "...";
From an understanding point of view, it's pleasing to a developer to see in other file:
import {
ACTION_1,
ACTION_2
} from './types.js'
At the end of the day, it's syntactic preference.
I am using Angular 1.6 with ES6. Until now I implemented inheritence with the extend keyword on ES6 classes
export default class myChildService extends myBaseService {
constructor(someDependency){
'ngInject'
super();
someDependency.doStuff();
}
}
and registered the child-class as angular-service
import myChildService from ./myChildService
angular.module('myApp', [])
.service('myChildService', myChildService)
This works well so far!
However I would like to split my application into smaller modules. This means I will have several different angular-modules which will need access to myBaseService in order to inherit the functionality.
I could just import the file containing myBaseService, but this seems not very angulary. It basically means I disregard angular-modules and DI everytime I use inheritance.
Question:
Is there any way to export an ES6-class from an angular-module base so that I can reuse it on an angular-module child which depends on base?
Maybe I am just looking at this the wrong way - if you have other suggestions to implement inheritance of angular-services/ factories using ES6-classes, please go ahead.
Why importing is not angulary? If you would like to use base service functionality, the module should know it's definition.
I am quite new to React and have been reading up a lot about it. I have come across three different methods to create components:
Functional Components:
const Hello = ({world}) => {
return (
<div>{"Hello" + world}</div>
);
}
React.createClass (Factory):
const Hello = React.createClass({
render: function() {
return <div>{"Hello" + this.props.world}</div>
}
});
ES6 Class Extends
class Hello extends React.Component {
render() {
return (
<div>{"Hello" + this.props.world}</div>
);
}
}
Apart from the obvious that the functional components don't have any state coupled to it and is probably a more functional approach to doing components, why would I use the different methods?
In the React documentation they use all three methods. Some of the Stack Overflow articles suggest the Class method and then some suggest the Factory method.
Using functional is recommended for components that are stateless.
Using React.Component extend is recommended if you are working with ES6+/TypeScript code. React Native has support only for this type of component creation.
React.createClass is for used with ES5.
Browsers will soon have a complete support and Facebook recommends to use React.Component instead of React.createClass and to use functional for stateless.
Edit
Facebook added a deprecation warning to React.createClass in React 15.6.0 and points users to use create-react-class instead.
As I know, it is recommend to use functional component when you need just create presentational logic component. For component that has any logic we use smth like React.createClass().
There are two ways of doing that:
First, you create general component and than divide it on presentational logic and business logic.
Second, you can create them alongside.
Be careful! When divide these components, your business logic must render your presentational logic!
For more practice see tutorials on the codecademy
I was looking at this fiddle for MobX and I've seen these two ways of defining React Components in ES6 other places as well, like Dan Abramov's egghead redux video series.
#observer
class TodoListView extends Component {
render() {
return <div>
<ul>
{this.props.todoList.todos.map(todo =>
<TodoView todo={todo} key={todo.id} />
)}
</ul>
Tasks left: {this.props.todoList.unfinishedTodoCount}
</div>
}
}
const TodoView = observer(({todo}) =>
<li>
<input
type="checkbox"
checked={todo.finished}
onClick={() => todo.finished = !todo.finished}
/>
<input
type="text"
value={todo.title}
onChange={ e => todo.title = e.target.value } />
</li>
);
My question is, when is it appropriate to use each type?
It seems like the simpler components are able to use the simpler syntax, but I'd like a rule or guideline to follow.
Thanks!
The second pattern is called "stateless functional components", and using it is recommended in almost all cases. SFCs (stateless functional components) are pure functions that are only dependent on their props. They are easier to test, decoupled from each other and will have significant performance gains over other patterns in the future. (source from the official react documentation)
They have a few gotchas though, namely:
One cannot attach refs to SFCs. (src, src2)
They cannot have internal state. (src)
They cannot use lifecycle methods. (e.g. componentDidMount, src)
If you need any of these things, first make sure there is no way around using them and only then use either the ES6 class or the React.createClass patterns.
I highly recommend "Should I use React.createClass, ES6 Classes or stateless functional components?" by James K Nelson to understand the tradeoffs and difference between these patterns, and "Presentational and Container Components" by Dan Abramov for an explanation of the most commonly used structure for Redux applications.
React.createClass VS ES2015 classes VS functional stateless components
In React, there are 3 main ways of creating a new component.
The first one to be introduced alongside with React library was React.createClass, which has the following syntax:
var TestComponent = React.createClass({
render: function(){
return <p>{this.props.children}</p>;
}
})
React.render(<TestComponent>This will be a paragraph element!</TestComponent>, document.body);
After that, in React 0.13 release, we could define our components directly as ES2015 classes:
class TestComponent extends React.Component {
render () {
return <p>{this.props.children}</p>;
}
}
React.render(<TestComponent>This will be a paragraph element!</TestComponent>, document.body);
React 0.14 introduces the ability to create those called stateless components, also known as functional or pure components because they are declared as a function that has no state and returns the same markup given the same props:
const TestComponent = (props) => <p>props.children</p>;
ReactDOM.render(<TestComponent>This will be a paragraph element!</TestComponent>,
document.querySelector('#root'));
These stateless components are much more lighter for React to render, and also have the advantage of being React agnostic, meaning that they can be rendered in any other way given the same input and will produce the same output.
So what you should use in your app depends. Each has their pros and cons and should be used under certain conditions. There are times when you can't use stateless components.
Use ES2015 (ES6) classes or React.createClass when your component needs lifecycle methods or you need to access 'this' for anything other than props.