How to use composition in ReactJs - javascript

Well here I want to use one method to another component, And for that I found a way through composition.
And this is what I did for that
file1.js
import ProductList from '../../views/Products/ProductList';
class CloseableTab extends Component {
constructor() {
super();
this.tpItem = () => {
console.log("hello, item clicked");
};
}
render() {
return (
<div>
<ProductList
itemChange={this.tpItem} />
</div>
);
}
}
export default CloseableTab;
Then in productList I want to call the "tpItem" method by calling itemChange in prop.
Though before that I tried to console the 'prop' of product list. So, it shows me null object in the console. And for that I used the code below:
ProductList.js
export default class ProductList extends Component {
constructor() {
super();
};
render() {
console.log(this.props);
return { }
}
}
So, this gives me null object in the console.
I'll appreciate your help, thanks.

Did you make constructor props enabled ?
Just pass props parameter in constructor
constructor(props) {
super(props)
}
The constructor for a React component is called before it is mounted.
When implementing the constructor for a React.Component subclass, you
should call super(props) before any other statement. Otherwise,
this.props will be undefined in the constructor, which can lead to
bugs.

Its not ideal to define functions in the constructor of the component, you can declare them outside of constructor and pass them down, also, in ProductList you are trying to render an object which isn't supported. if you don't want to return anything use return null.
Below code works as expected.
class CloseableTab extends Component {
constructor() {
super();
this.tpItem = () => {
console.log("hello, item clicked");
};
}
render() {
console.log(this.tpItem);
return (
<div>
<ProductList
itemChange={this.tpItem} />
</div>
);
}
}
class ProductList extends Component {
render() {
console.log(this.props);
return null
}
}
However you must write it like
class CloseableTab extends Component {
tpItem = () => {
console.log("hello, item clicked");
};
render() {
console.log(this.tpItem);
return (
<div>
<ProductList
itemChange={this.tpItem} />
</div>
);
}
}
Working sandbox

Related

React - passing 'this' as a prop

Is there any side effect I do not see by doing this ?
class App extends React.Component {
hello() {
console.log("hello")
}
render() {
return <Layout app={this}>
}
}
So later on I can refer to this.props.app.hello (and others) from Layout ?
This is not safe.
React will not know how to watch for changes, so you may miss re-renders. React uses === to check for state changes, and App will always be === to App, even when state or properties change.
Take this example:
class App extends React.Component {
constructor(props) {
super(props);
this.setState({text: 'default value'});
}
hello() {
this.setState({...this.state, text: 'new value'});
}
render() {
return (
<div onClick={this.hello}>
<Layout app={this}>
</div>
);
}
}
class Layout extends React.Component {
render() {
return <div>{this.app.state.text}</div>
}
}
When you click on the parent div, this.hello will be called, but the child component will not detect the state update, and may not re-render as expected. If it does re-render, it will be because the parent did. Relying on this will cause future bugs.
A safer pattern is to pass only what is needed into props:
class App extends React.Component {
//...
render() {
return (
<div onClick={this.hello}>
<Layout text={this.state.text}>
</div>
);
}
}
class Layout extends React.Component {
render() {
return <div>{this.props.text}</div>
}
}
This will update as expected.
Answer
There's nothing wrong in passing functions as props, as I can see in your example, the only thing you have to do is make sure your function is bound to the current component like the following example
Reference
React: Passing Functions to Components

React, this.props is not defined

I know this is a very common problem and I looked into many other complaints before posting this.
I have class Parent
class Parent extends React.Component {
constructor() {
super();
this.state = {
...
};
}
....
render() {
return (
<MuiThemeProvider theme={materialTheme}>
<Child
ref={...}
groupId={this.state.groupId}
groupUniqueId={this.state.groupUniqueId} />
</MuiThemeProvider>
);
}
}
And a class Child
class Child extends React.Component {
constructor() {
super(props);
this.state = {
...
};
...
}
getUsers() {
const url = `/someurl/${this.props.groupId}`;
...
}
render() {
return (...);
}
}
export default Child;
However, in the class Child, I get an error
"Uncaught ReferenceError: props is not defined"
Is there something obvious that I am missing? Thanks!
This is happening because your this is not referencing a class. It is referring to your function. You can either use arrow functions or bind this to your function in constructor. Just add below line
constructor() {
super(props);
this.state = {
...
}
this.getUsers = this.getUsers.bind(this)
}

React HOC - Access wrapped component function

PRESENTATIONAL COMPONENT
class ClientsPage extends React.Component {
_myFunction() {
//do what needs to be done
}
render() {
return <div></div>
}
}
export default doMagic(ClientsPage)
HOC COMPONENT
export const doMagic= (WrappedComponent) => {
return class MyMagic extends React.Component {
render() {
const props = Object.assign({}, this.props , {
xxx: ???,
});
return <WrappedComponent { ...props } />
}
};
}
Hi guys, i have react component and want to transform it in some way in my HOC component.
But heres the problem. I want to create another prop lets call it xxx in HOC. This prop will be of type object and one of properties of this object should be function from wrapped component so womething like
xxx : {callback : reference to function from wrapped component}
Is this even possible ?
thx in advance
You can do callback to wrapped component's function with WrappedComponent.prototype._myFunction()
const doMagic= (WrappedComponent) => {
return class MyMagic extends React.Component {
render() {
const props = Object.assign({}, this.props , {
xxx: WrappedComponent.prototype._myFunction()
});
return <WrappedComponent { ...props } />
}
};
}
class ClientsPage extends React.Component {
_myFunction() {
return "Wrapped Component Function Callback Done..!";
}
render() {
return <div>Hello {this.props.xxx}</div>
}
}
export default doMagic(ClientsPage)
You can see the working jsfiddle here https://jsfiddle.net/12ojjddw/
If you want to access WrappedCompoent props, then you need to use Inheritance Inversion, it is a bit more complex, but allows you full control, here is a good explanation:
https://medium.com/#franleplant/react-higher-order-components-in-depth-cf9032ee6c3e

React - props is empty when calling a callback function from child

I have a button on my main component, when its clicked its open an "Approval pannel", And when the OK is clicked I am calling a callback function to the main component and doing some logic.
I want to pass the callback function(My reasons), The problem is that when the callback function is called, the props and state are undefined.
Why is that happening? Please tell me if any info is missing.
I have added a partial code here:
class MainComponent extends React.Component {
constructor(props){
currentActionConfig = {onOkClick: this.onGenericApprovalOkClicked, ...};
}
onCommandApprovalOkClicked(commandText){
console.log(this.props); <- 'undefined'
}
render(){
return <ActionsApprovalPanel currentActionConfig={this.currentActionConfig}/>
}
}
export default class ActionsApprovalPanel extends React.Component {
render()
{
...
return <ChangeIpApproval onOkClick={this.props.currentActionConfig.onOkClick}/>;
...
}
}
Try these changes
class MainComponent extends React.Component {
constructor(props){
super(props); //1. Call super
this.currentActionConfig = {onOkClick: this.onGenericApprovalOkClicked.bind(this), ...}; // 2.bind this
}
onCommandApprovalOkClicked(commandText){
console.log(this.props); <- 'undefined'
}
render(){
return <ActionsApprovalPanel currentActionConfig={this.currentActionConfig}/>
}
}
export default class ActionsApprovalPanel extends React.Component {
render()
{
...
return <ChangeIpApproval onOkClick={this.props.currentActionConfig.onOkClick}/>;
...
}
}
I think you need to make few changes to your React component.
First: In the constructor call super().
Second:: Define currentActionConfig as a state and try using it as this.state.currentActionConfig
Third: Specify the binding on onCommandApprovalOkClicked(). as
onCommandApprovalOkClicked = (commandText) => {} and similary for other functions.
class MainComponent extends React.Component {
constructor(props){
super(props);
this.state = {
currentActionConfig = {onOkClick: this.onGenericApprovalOkClicked, ...}
};
}
onCommandApprovalOkClicked(commandText){
console.log(this.props); <- 'undefined'
}
render(){
return <ActionsApprovalPanel currentActionConfig={this.state.currentActionConfig}/>
}
}
export default class ActionsApprovalPanel extends React.Component {
render()
{
...
return <ChangeIpApproval onOkClick={this.props.currentActionConfig.onOkClick}/>;
...
}
}
Make these changes and see if they work.

Creating an HOC gives Super expression must either be null or a function, not object

I'm creating a decorator or a higher-order component (HOC) for my project, which takes in a factory function, and returns another function, which wraps over the component, like this:
class X extends React.Component {
render() {
return <div>Hi</div>
}
}
export default Decorator(factory)(X);
or
#Decorator(factory)
export default class X extends React.Component {
render() {
return <div>Hi</div>
}
}
The code for my decorator is like this:
export default function Decorator(factoryFn) {
return function decorate(Component) {
return class DecoratedComponent extends Component {
static contextTypes = {
allStyles: PropTypes.object.isRequired,
}
render() {
const gStyles = factoryFn(this.context.allStyles);
return (
<Component {...this.props} gStyles={gStyles} />
);
}
};
};
}
On running this, I'm getting an error from babel-runtime/inherits.js, which says: Super expression must either be null or a function, not object.
What is the correct way to create a decorator or HOC which works like I've described above?

Categories

Resources