File1.tsx
class abc extends <abcProps, abcstate>
{
constructor(){...}
}
class def extends abc {
constructor(){
super(props)
}
}
export default{
def_var: (props) => React.createElement(def, props)
}
File2.tsx
class xyz extends React.Component<xyzProps, xyzState> {
//I want to make def the child of this classi.e xyz
render(){
return
<div>
<def .../>
</div>
}
}
I have made a subclass child of another component, and the methods in parent class abc are not functioning properly.
The way your sample code is written, the constructor in component def doesn't accept any props -- so calling super(props) doesn't actually do anything.
Using vanilla JavaScript, here's an example doing exactly what you're asking for:
class Hello extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
class HelloExtension extends Hello {
constructor(props) {
super(props);
}
}
class XYZ extends React.Component {
render() {
return (
<div>
<h1>Inside XYZ Component</h1>
<HelloExtension name="World" />
</div>
)
}
}
ReactDOM.render(
<XYZ />,
document.getElementById('container')
);
The only difference in TypeScript is the strong typing of the props and state interfaces, which you already have in your example.
See a JS fiddle here.
Related
Let say I have this Parent
const Parent = () => <ChildComponent foo={<Button>clic</Button>} />
why would this code work
class ChildComponent extends React.Component {
render() {
return (
<div>
{this.props.foo}
</div>
)
}
}
but this code would not ?
class ChildComponent extends React.Component {
constructor(props) {
super(props)
const ParentButton = this.props.foo
}
render() {
return (
<div>
<ParentButton />
</div>
)
}
}
I need something like the second example in order to add some event to ParentButton.
I'd like to make this example work with class defined component
Update :
Based on answer I now have a partial solution
class ChildComponent extends React.Component {
constructor(props) {
super(props)
this.ParentButton = this.props.foo
}
render() {
return (
<div>
{this.ParentButton}
</div>
)
}
}
You're not assigning ParentButton to the ChildComponent.
What you currently have is a const floating in the constructor since const, let and var keywords are function/block scoped.
this. ParentButton = this.props.foo and succinctly <this. ParentButton > in your render function will get you what you're after.
I am trying to set state of the parent class with the child. But having trouble figuring out how to do this. I've abstracted away anything I deemed irrelevant to the question at hand. The issue is that I am
Class Parent extends Component {
constructor(props){
super(props)
this.state = {
foo: "bar"
}
}
coolMethod(n){
this.setState({foo: n})
}
render{
return(
<Child coolmethod={this.coolMethod} />
)
}
}
Class Child extends Component {
constructor(props){
super(props)
}
componentDidMount(){
let that = this;
videojs('my-player', options, function onPlayerReady() {
this.on('end',()=>{
that.props.coolMethod(<whatever string returns as a result of
this method>)
})
})
}
render{
return(
// irrelevant stuff to this question
)
}
}
Currently this code gives me "type error: this.setState is not a function"
If you want more info on videojs: http://videojs.com/ (though this is irrelevant to the question by itself, other than the fact that I reference it in my videojs call in componentDidMount of the child)
I assume the 2nd class is Class Child extends Component .... You need to bind this.coolMethod in your Parent constructor first.
Class Parent extends Component {
constructor(props){
super(props)
this.state = {
foo: "bar"
}
this.coolMethod = this.coolMethod.bind(this);
}
coolMethod(n){
this.setState({foo: n})
}
render{
return(
<Child coolmethod={this.coolMethod} />
)
}
}
Try this, tested working on my side, found two issues in the code
Javascript is case sensitive coolmethod is passed in to the Child, but you are trying to access coolMethod.
You need this > this.coolMethod = this.props.coolMethod.bind(this); in the constructor to inherit the setState function from the Parent, otherwise, this inside the coolMethod will be undefined.
import React, { Component } from 'react';
export default class Parent extends Component {
constructor(props){
super(props)
this.state = {
foo: "bar"
}
}
coolMethod(n){
this.setState({foo: n})
}
render(){
return(
<Child coolMethod={this.coolMethod} />
)
}
}
class Child extends Component {
constructor(props){
super(props)
this.coolMethod = this.props.coolMethod.bind(this);
}
render(){
return(
<button onClick={() => this.coolMethod("aabbcc")}>1</button>
)
}
}
I tried to dynamically pass a reference to a class to a container and render it.
class Test extends React.Component{
render() {
return <div>Test</div>
}
}
class HelloWidget extends React.Component{
constructor(props) {
super(props);
this.state = {
child: Test
};
}
render() {
return <div>{this.state.child}</div>;
}
}
React.render(<HelloWidget />, document.getElementById('container'));
See it at jsfiddle: https://jsfiddle.net/coolshare/jwm6k66c/2720/
It did not render anything...
Any suggestion?
thanks
You can dynamically change the state value in HelloWidget component and that would reflect in Test Component.
Here is the code:
class Test extends React.Component{
render() {
return <div>{this.props.child}</div>
}
}
class HelloWidget extends React.Component{
constructor(props) {
super(props);
this.state = {
child: "Test"
};
}
render() {
return <div>
<Test child={this.state.child}/>
</div>;
}
}
React.render(<HelloWidget />, document.getElementById('container'));
Here is a working fiddle link: https://jsfiddle.net/jayesh24/1uvpg5ej/
You need to use React.createElement to create the new react element.
Like this:
render() {
return <div>hello {React.createElement(this.state.child)}</div>;
}
Check the working fiddle.
Use the Directive of your Test inside the constructor to create that component when you are assigning
this.state = {
child: <Test />
};
I have two components. I want to call a method of the first component from the second component. How can I do it?
Here is my code.
First Component
class Header extends React.Component{
constructor(){
super();
}
checkClick(e, notyId){
alert(notyId);
}
}
export default Header;
Second Component
class PopupOver extends React.Component{
constructor(){
super();
// here i need to call Header class function check click....
// How to call Header.checkClick() from this class
}
render(){
return (
<div className="displayinline col-md-12 ">
Hello
</div>
);
}
}
export default PopupOver;
You can do something like this
import React from 'react';
class Header extends React.Component {
constructor() {
super();
}
checkClick(e, notyId) {
alert(notyId);
}
render() {
return (
<PopupOver func ={this.checkClick } />
)
}
};
class PopupOver extends React.Component {
constructor(props) {
super(props);
this.props.func(this, 1234);
}
render() {
return (
<div className="displayinline col-md-12 ">
Hello
</div>
);
}
}
export default Header;
Using statics
var MyComponent = React.createClass({
statics: {
customMethod: function(foo) {
return foo === 'bar';
}
},
render: function() {
}
});
MyComponent.customMethod('bar'); // true
Well, actually, React is not suitable for calling child methods from the parent. Some frameworks, like Cycle.js, allow easily access data both from parent and child, and react to it.
Also, there is a good chance you don't really need it. Consider calling it into existing component, it is much more independent solution. But sometimes you still need it, and then you have few choices:
Pass method down, if it is a child (the easiest one, and it is one of the passed properties)
add events library; in React ecosystem Flux approach is the most known, with Redux library. You separate all events into separated state and actions, and dispatch them from components
if you need to use function from the child in a parent component, you can wrap in a third component, and clone parent with augmented props.
UPD: if you need to share some functionality which doesn't involve any state (like static functions in OOP), then there is no need to contain it inside components. Just declare it separately and invoke when need:
let counter = 0;
function handleInstantiate() {
counter++;
}
constructor(props) {
super(props);
handleInstantiate();
}
You could do this to call a method of the child component from the parent component.
import React from 'react';
class Header extends React.Component {
constructor() {
super();
this.childComponentRef;
}
getChildComponent = (childComponent) => {
this.childComponentRef = childComponent;
this.childComponentRef.sayHi();
}
render() {
return (
<ChildComponent getChildComponent={this.getChildComponent} />
)
}
};
class ChildComponent extends React.Component {
componentDidMount () {
this.props.getChildComponent(this);
}
sayHi = () => {
alert("hi");
}
render() {
return (
<div className="displayinline col-md-12 ">
Hello
</div>
);
}
}
export default Header;
I'm trying to use ES6 classes inside of React, and want all my components to inherit certain methods, however as soon as I try to extend a component which extends the React.Component class, the componentDidMount method doesn't trigger and hence nothing gets rendered. The code I'm using:
BaseComponent.jsx
import React from 'react';
class BaseComponent extends React.Component {
constructor() {
super();
console.log('BaseComponent constructor');
}
render() {
return (
<div>Hello, Im the base component</div>
);
}
}
export default BaseComponent;
ExampleComponent.jsx
import BaseComponent from './BaseComponent';
class ExampleComponent extends BaseComponent {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('exampleComponent mounted');
}
render() {
return (
<div>Hello, Im the example component</div>
);
}
}
export default ExampleComponent;
App.jsx
import React from 'react';
React.render(<ExampleComponent />, document.body);
I'm using React 0.13.3, and using babelify 6.1.2 to transpile.
The string 'exampleComponent mounted' never gets logged to console, and nothing is rendered. Any ideas what I'm doing wrong?
I'm not sure about the approach, but this code also works:
export default class Service extends BaseComponent {
componentDidMount(...args) {
super.componentDidMount.apply(this, args);
}
}
UPD: this is considered to be a bad practice though:
a) https://medium.com/#dan_abramov/how-to-use-classes-and-sleep-at-night-9af8de78ccb4
b) https://medium.com/#dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750
I think, the problem is that you cannot create deeper class-structures for react components. Also, you shouldn't have to need it. On your example the BaseComponent is useless anyway.
Try this instead:
import React from 'react';
export default class ExampleComponent extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('exampleComponent mounted');
}
render() {
return (
<div>Hello, Im the example component</div>
);
}
}
If you want to create 'BaseComponents', you could implement them as mixins or simply as 'sub components'.
This could look like this:
import React from 'react';
import BaseComponent from './BaseComponent';
export default class ExampleComponent extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('exampleComponent mounted');
}
render() {
return (
<div>
<div>Hello, Im the example component</div>
<BaseComponent />
</div>
);
}
}
EDIT: Also possible:
import React from 'react';
import BaseComponent from './BaseComponent';
export default class ExampleComponent extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('exampleComponent mounted');
}
render() {
return (
<BaseComponent
<div>Hello, Im the example component</div>
</BaseComponent>
);
}
}
// BaseComponent.js
render() {
return {
<div>
<div>Hello, Im the base component</div>
{this.props.children}
</div>
}
}
EDIT #2: Above code works fine with es5/jsx syntax.
DEMO