I am learning react and I am trying to call a class from a method. Here is what I have came up so far
class Pop extends React.Component{
render(){
return (
<div>
<button onClick={() => { this.desit("data")} }>Componant Caller</button>
</div>
)
}
desit(data){
<Test info={data}/>
}
}
class Test extends React.Component{
render(){
return
<div>{alert(this.props.info)}</div>
}
}
ReactDOM.render(<Pop />,document.getElementById("targ"));
Help please?
You want to have a method in a separate class and trigger it from the Component?
Don't use another component, but you can create a regular class with some logic:
class Test
{
test() {
alert('success!');
}
}
In the desit method, you can now invoke Test.test(), like this:
desit() {
var amazingTest = new Test();
amazingTest.test();
}
You could use a static method as well:
class Test
{
static test() {
alert('success!');
}
}
// and the desit method:
desit() {
Test.test();
}
Related
I have react component and I need make instance of class like observable.
#observer
class A extend React.Component {
// make observable
instance = new B();
render (){
<div>
<div onClick={() => this.instance.setName('Joe')}/>
// should update
<div>{this.instance.name}</div>
</div>
}
}
Class that we inject:
class B {
#observabe
_name: string
#action
setName(name: string) {
this._name = name;
}
}
Okay, I just forgot to bind context. You can use either arrow function or #action.bind.
In my lit-element I'm rendering something based on an outside variable. How can I know to update when that variable changes?
import { LitElement, html } from 'lit-element';
import './element01.js';
class Layout extends LitElement {
createRenderRoot(){ return this; }
static get properties() {
return {
settings: { Object }
};
}
constructor() {
super();
}
render() {
return html`
${(settings.foo === 'bar')? html`<my-element01 />` : null}
`;
}
}
customElements.define('my-layout', Layout);
The settings object is being modified outside, how can this element know to update? I'm not using any other framework.
The index.html file should always have a
<my-app></my-app>
Within the my-app element, you will be able to use all the features of litElement such as
class MyApp extends LitElement {
static get properties() {
return {
prop: {type: Object},
};
}
render() {
return html`
<my-element .prop="${this.prop}"</my-element>
<my-server .prop="${this.prop}"</my-server>
<button #onClick='${(e) => this.prop += 1}' >change the settings value</button>
`;
}
}
Here one example I tried to illustrate. settings property changed outside of litElement and effected in litElement.
demo
index.html
...
<my-layout></my-layout>
<br>
<button onClick="_buttonClicked()" >change the settings value</button>
<script>
document.querySelector('my-layout').settings={foo:"bar"};
function _buttonClicked (e) {
document.querySelector('my-layout').settings = {foo:"baz"};
}
</script>
my-layout :
import { LitElement, html } from 'lit-element';
//import './element01.js';
class Layout extends LitElement {
createRenderRoot(){ return this; }
static get properties() {
return {
settings: { Object }
};
}
constructor() {
super();
}
render() {
return html`
${this.settings.foo === 'bar'? html`<span> element01 will be rendered</span>` : null}
`;
}
}
customElements.define('my-layout', Layout)
I made some syntax corrections
I am using typescript and i am writing a custom decorator for one of my angular class. I want to access the base class method in the child class decorator. Or access base class methods using the child class prototype. Is there any way to do this? Problem explained in detail below.
Scenario
I have a base class which is like
export class Base {
public init() {
console.log('My base class function');
}
}
And i have a derived class which extends this base class
export class Child extends Base {
}
What i am trying to do
I am trying to write a decorator for the derived class something like
#TestDecorator(['init'])
export class Child extends Base {
}
which will call the init method from the base class.
What is the issue
To do the above scenario, i have written code something like below
export function Tool<T extends Base>(methods: any[]) {
return function (target: Function) {
methods.forEach((item) => {
if (item === 'init') {
target.super.init() // Stuck here
}
})
}
}
I am not understanding how to make the following line work
target.super.init() // Stuck here
Please help me with the solution. I am stuck. Thanks
I believe you are looking for something like this:
export function Tool<T extends Base>(methods: any[]) {
return function (target: Function) {
return class extends target {
constructor(...args: any[]) {
super(...args)
methods.forEach((item) => {
if (item === 'init') {
super.init( );
}
})
}
}
}
}
To expand on Paulpro's answer, since the decorator function is returning a substitute for the constructor of the class that it is decorating, it must maintain the original prototype.
In the following example, there is an error due to the missing init() method in TestDecorator<Base>.
Typescript Playground Demo
class Base {
public init() {
console.log('My base class function');
}
}
function TestDecorator<T extends Base>(methods: any[]) {
return function (target: any) {
return class extends target {
constructor(...args: any[]) {
super(...args)
methods.forEach((item) => {
if (item === 'init') {
super.init( );
}
})
}
}
}
}
#TestDecorator(['init']) // Error: Property 'init' is missing in type 'TestDecorator<Base>.(Anonymous class)' but required in type 'Child'.
class Child extends Base {
}
let c = new Child();
Corrected Decorator
function TestDecorator<T extends Base>(methods: any[]) {
return function (target: any) {
return class extends target {
init() {} // Define init()
constructor(...args: any[]) {
super(...args)
methods.forEach((item) => {
if (item === 'init') {
super.init( );
}
})
}
}
}
}
Class Decorators
If the class decorator returns a value, it will replace the class declaration with the provided constructor function.
NOTE: Should you choose to return a new constructor function, you must take care to maintain the original prototype. The logic that applies decorators at runtime will not do this for you.
I'm extending a base class and overriding a method in the base class. But when I call it, it calls the super class version. How do I override the method?
var Hello = React.createClass( {
getName: function() { return "super" },
render: function() {
return <div>This is: {this.getName()}</div>;
}
});
class HelloChild extends Hello {
constructor(props) {
super(props);
console.log( this.getName());
}
getName()
{
return "Child";
}
};
I want it to print "This is: Child" but it prints "This is: super"
The problem is that you're mixing ES6 type class declaration (ex. Hello) with old school Javascript declaration (ex. HelloChild). To fix HelloChild, bind the method to the class.
class HelloChild extends Hello {
constructor(props) {
super(props);
this.getName = this.getName.bind(this); // This is important
console.log( this.getName());
}
getName()
{
return "Child";
}
};
Then it'll work.
I found the answer (adapted from here: https://gist.github.com/Zodiase/af44115098b20d69c531 ) - the base class needs to also be defined in an ES6 manner:
class Hello extends React.Component {
//abstract getName()
getName()
{
if (new.target === Hello) {
throw new TypeError("method not implemented");
}
}
render() {
return <div>This is: {this.getName()}</div>;
}
};
Actually you can override method to execute code from your subclass
class Hello extends React.Component {
getName() {
super.getName();
}
}
class HelloChild extends Hello {
getName()
{
return "Child";
}
}
Please note that this answer proposes different approach:
I wonder why you should do this in the first place, my point is that directly coupling two react components is not a right way to implement re-usability in React.
If you are trying to have multiple child components which extends one parent, What I would do is, to have child components and a higher-order component and then implement common functionality with Composition. This way you can skip those methods, which you were trying to override and so everything would stay clear.
I would like to add <p> tag in ExtendedComponent by calling super.render(), Problem is I don't know whether it is possible to modify already defined jsx object. Ideal would be to just write parentTemplate + <p>Some paragraph</p>, but that doesn't work.
class BaseComponent extends React.Component {
get title() {
return 'I am base component';
}
render() {
return <h1>Hello {this.title}</h1>;
}
}
class ExtendedComponent extends BaseComponent {
get title() {
return 'I am extended component';
}
render() {
var parentTemplate = super.render();
// append <p>Some paragraph</p> to parentTemplate
return parentTemplate;
}
}
ReactDOM.render(
<ExtendedComponent />,
document.getElementById('test')
);
Like azium mentioned in the comments, this is not common to do with react. However, if you need to do it, it can be accomplished like this:
render() {
var parentTemplate = super.render();
// append <p>Some paragraph</p> to parentTemplate
return <div>{parentTemplate}<p>Some paragraph</p></div>;
}
You have to wrap it inside a div since a react element only can return one element, not a list of them. parentTemplate is just like any other jsx, but it's in a variable. You use the {variableName} syntax to add variables into the JSX.
Another way to do this, which is more "react"-like:
class BaseComponent extends React.Component {
render() {
return <h1>Hello {this.props.title}</h1>;
}
}
BaseComponent.propTypes = {
title: React.PropTypes.string
};
BaseComponent.defaultProps = {
title: 'I am base component'
};
class ExtendedComponent extends React.Component {
render() {
return (
<div>
<BaseComponent title="I am extended component"/>
<p>Some paragraph</p>
</div>
);
}
}
ReactDOM.render(
<ExtendedComponent />,
document.getElementById('test')
);
JSFiddle
Here ExtendedComponent is a higher-order component rather than one that inherits from BaseComponent. Most of the time this is a seperation of concerns that is easier to reason about, and most react apps are built this way rather than on inheritation.
Hope this helps!