How can I wrap React component? - javascript

I need to wrap a React node into this function:
export const foo = (WrappedComponent: *) => {
class fooRenderer extends Component<any> {
render() {
const { bar, ...props } = this.props;
if (bar) {
...
}
return <WrappedComponent {...props} />;
}
}
return fooRenderer;
};
I tried the following:
class MyWrappedComponent extends React.Component {
render() {
...
return foo(
<MyComponent
a={a}
b={b}
</MyComponent>
);
}
}
and received the following error:
Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
So essentially I need to render foo(Component_instance).

you can create your react component out of the function
class fooRenderer extends Component{
render(){
return(
<div>Component</div>
)
}
}
after that call the component in your function
export default function wrappedComponent(a, b){
return <fooRenderer a={a} b={b}/>
}
react component at the deep is function if you like to know

Related

Spreading props in React Higher Order Components

I am trying to go very in-depth to understand the purpose of spreading props in React HOC
So taking the below example;
const EnhanceComponent = BaseComponent => {
return class EnhancedComponent extends Component {
state = {
name: 'You have been enhanced'
}
render() {
return (
<BaseComponent {...this.props} {...this.state} />
)
}
}
};
export default EnhanceComponent;
Now let's say the usage of BaseComponent is as below;
<BaseComponent className='wrapper-container' onClick={this.handleClick} />
I assume if had not spread the props in the HOC, we would have been unable to access "this.props.className" OR "this.props.onClick" in BaseComponent. Would that be correct understanding ?
class BaseComponent extends React.Component {
render() {
const { className, onClick} = this.props;
...
}
}
Now to use the HOC itself, we would say;
const EnhancedMyComponent = EnhanceComponent(MyComponent);
And render it as
<EnhancedMyComponent className='wrapper-container' onClick={this.handleClick} />
Now, below are my 2 specific questions;
What do we finally render i.e. BaseComponent or EnhancedMyComponent OR using HOC allows us to use either flavor e.g. in some case, if we do not want the enhanced functionality, we just use the base component ?
OR
<EnhancedMyComponent className='wrapper-container' onClick={this.handleClick} />
Would the props access issue i.e. if we do not spread the props be applicable in both the above cases of consumption i.e. <BaseComponent /> AND <EnhancedMyComponent /> ?
1) What do we finally render i.e. BaseComponent or EnhancedMyComponent OR using HOC allows us to use either flavor e.g. in some case, if we do not want the enhanced functionality, we just use the base component ?
/ Using HOC allows us to use either flavor. It totally depends where we are wrapping the Component in HOC i.e while exporting or while using it at someplace.
Now, In the below case one has the option to use it with or without HOC
// BaseComponent.js
class BaseComponent extends React.Component {
render() {
const { className, onClick} = this.props;
...
}
}
export default BaseComponent;
// SomeComponent.js
import BaseComponent from './BaseComponent';
const MyComponent = EnhanceComponent(BaseComponent);
class SomeComponent extends React.Component {
render() {
return (
...
<MyComponent className={...} onClick={...} someExtraPropForHOC={...}/>
<BaseComponent className={...} onClick={...} />
...
)
}
To not allow anyone to directly use the Component, wrap it in HOC and export
// BaseComponent.js
class BaseComponent extends React.Component {
render() {
const { className, onClick} = this.props;
...
}
}
export default EnhanceComponent(BaseComponent);
// SomeComponent.js
import BaseComponent from './BaseComponent';
class SomeComponent extends React.Component {
render() {
return (
...
<BaseComponent className={...} onClick={...}/>
...
)
}
2) Would the props access issue i.e. if we do not spread the props be applicable in both the above cases of consumption i.e. AND ?
/ Spread the props is needed as HOC does not know what props would be needed for the dynamically wrapped component. So pass all the props which are coming is the only possible way.
class BaseComponent extends React.Component {
render() {
const { className, onClick} = this.props;
...
}
}
class CustomTextField extends React.Component {
render() {
const { className, onKeyPress, value} = this.props;
...
}
}
const EnhancedBaseComponent = EnhanceComponent(BaseComponent);
const EnhancedTextComponent = EnhanceComponent(CustomTextField);
Now in this case EnhancedBaseComponent and EnhancedTextComponent both need different props, but since they are wrapped in EnhanceComponent. It won't know which props to pass. So spread it and send all the props coming to it.

How to use composition in ReactJs

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

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 js access to the state of another class

How can I access the state of another class.
This construction does not work
class classname2 extends React.Component {
...
this.state = { statename1: "lala" };
...
};
class classname1 extends React.Component {
render() {
return (
{classname2.state.statename1 }
);
}
};
As mentioned in the comments, pass state as props to their children.
class classname2 extends React.Component {
this.state = { statename1: "lala" };
render() {
return <classname1 statename1={this.state.statename1} />
}
};
class classname1 extends React.Component {
render() {
return (
<div>{this.props.statename1}</div>
);
}
};
An often used pattern is passing arbitrary props down the component tree:
const {needThisOne, andThisOne, ...props} = this.props;
// do stuff with needThisOne andThisOne
// and pass the remaining props down:
return <Component {...props} />;
An update for hooks, because why not.
const ParentComponent = ({...props}) => {
const [stateName1, setStateName1] = useState('defaultValue');
return <ChildComponent stateName1={stateName1} {...props} />;
}
const ChildComponent = ({stateName1, ...props}) => (
<span>{stateName1}</span>
);
Shared state between components by direct access is an anti-pattern. Each component should have its own state. If you need globally a available state, please consider using Redux.
It may sound a bit cumbersome at first but it's awesome and it allows your app to be properly tested.
Edit:
Passing state as props is also valid, but it only works when components are in parent-child order. Redux allows components to be updated no matter what their relationship is

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