How to contatenate React JSX objects - javascript

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!

Related

calling a class from a method

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();
}

React propTypes outside Component

I was into functional Javascript previously, Recently I started with Object oriented Javascript and React Library. This question is more of understanding the code.
Why below code don't work
class MyComponent extends React.Component{
propTypes : {
name: React.PropTypes.string.isReequired,
location: React.PropTypes.string
}
render(){
return(
<h1>Hello This is {this.props.name} and I live in
{this.props.location}</h1>
);
}
}
ReactDOM.render(
<MyComponent name="Node" location="DOM"/>,
document.getElementById('root')
);
Whereas this code works,
class MyComponent extends React.Component{
render(){
return(
<h1>Hello This is {this.props.name} and I live in {this.props.location}</h1>
);
}
}
MyComponent.propTypes = {
name: React.PropTypes.string.isReequired,
location: React.PropTypes.string
}
ReactDOM.render(
<MyComponent name="Node" location="DOM"/>,
document.getElementById('root')
);
Can someone help me understand this? Thanks.
You need to use static word (to define the static property) because, propTypes need to be declared on the class itself, not on the instance of the class , and use =.
Check the DOC.
Like this:
static propTypes = {
name: React.PropTypes.string.isRequired,
location: React.PropTypes.string
}
Inside an ES6 class, static properties look like this
class X extends Y {
static staticThing = {
...
}
}
note the =
"assigning" a static property the ES5 way looks like the second way you have it there
Typically, you'll use the second way for functional components whereas you might as well use the first way (albeit properly with an =) for ES6 style class components.
also, make sure you have your React.PropTypes correct - isReequired should be isRequired

How to override a parent class method in React?

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.

React extends defautProps

I am still on the way of the conquest React. I prefer to use a es6 component-based approach when creating React classes. And I detained at the moment when it is necessary to inheritance of some existing class with already defined defaultProps static property.
import {Component} from 'react';
class MyBox extends Component {
}
// Define defaultProps for MyBox
MyBox.defaultProps = {
onEmptyMessage: 'Nothing at here'
}
When I define a static property defaultProps of class that extend MyBox, it completely overwrites defaultProps of parent class.
class MyItems extends MyBox {
render() {
// this.props.onEmptyMessage is undefined here
// but this.props.onRemoveMessage is present
return <i>{this.props.onEmptyMessage}</i>; //<i></i>
}
}
// Define defaultProps for MyItems
MyItems.defaultProps = {
onRemoveMessage: 'Are you sure?'
}
But i need to extend defaultProps of parent class, not overwrite. I understand that is possible by extending directly defaultProps property of parent class.
MyItems.defaultProps = _.extend(MyBox.defaultProps, {
onRemoveMessage: 'Are you sure?'
});
But i think that such trick is dirty. Is there a way to perform it according to React plan?
In my opinion you the issue is not how you can merge the properties but how you can compose it without extending. You would have your components like this:
class MyBox extends Component {
static defaultProps = { title: 'Box title' }
render() {
return (
<div className={'mybox ' + this.props.className}>
<h1>{this.props.title}</h1>
{this.prop.children}
</div>
)
}
}
class MyItems extends Component {
render() {
return (
<MyBox className="itembox" title="Items title">
<i>{this.props.children}</i>
</MyBox>
)
}
}
Then use it like that
<MyBox>
box
</MyBox>
or
<MyItems>
items box
</MyItems>
That will render:
<div class="mybox">
<h1>Box title</h1>
box
</div>
or
<div class="mybox itembox">
<h1>Items title</h1>
<i>items box</i>
</div>
It looks like you have extending/overriding the className or the title, but you have composed. If you use this way of building your UI, you'll see it will be easier and faster

escaping html tags in meteor react

I have the following react component
homeComponent = React.createClass({
mixins: [ReactMeteorData],
getMeteorData() {
return {
homeData: homeContent.findOne()
}
},
render(){
let homeData = this.data.homeData;
return (
<div className="units-container home-container">
<h1>ply</h1>
<p>{homeData.homeCopy}</p>
Download
</div>
)
}
})
The key {homeData.homeCopy} returns a string that has html tags in. So in this case let's say it returns <strong>bold text</strong> not bold text.
I'm using react-template-helper to use both blaze and react, so I would expect that I could use triple brackets to escape the html, but that's not working. I need to escape the html from react I suppose.
How can I get react to honor these html tags from the string?
#mason505 pointed this in the right direction, but I think this needs some extra information.
First you must make a function to parse the html:
function escapeHTML(data) {
return {__html: data}
}
Then you must call that with dangerouslySetInnerHTML but only on a self enclosed html element and you must pass the data into dangerouslySetInnerHTML using the escapeHTML function. Complete example is:
function escapeHTML(data) {
return {__html: data}
}
homeComponent = React.createClass({
mixins: [ReactMeteorData],
getMeteorData() {
return {
homeData: homeContent.findOne()
}
},
render(){
let homeData = this.data.homeData;
return (
<div className="units-container home-container">
<h1>ply</h1>
<p dangerouslySetInnerHTML={escapeHTML(homeData.homeCopy)} />
Download
</div>
)
}
})

Categories