React Hoc function return class - reactjs

Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
import './App.css';
import React, { Component } from 'react';
const OOO = () => {
//console.log(this.props.children)
return class extends Component {
render() {
return (
<Rem {...this.props} />
);
}
}
}
class Rem extends Component {
render() {
return (
<p>Helo</p>
)
}
}
export default OOO;

This may happen if you return a Component instead of <Component /> from render
That is exactly what you are doing here. Calling <OOO /> returns a class instead of a JSX element.
This isn't really a higher-order component because you are not taking the inner component Rem as an argument. Did you intend to? That would look something like this:
const withOOO = (InnerComponent) => {
return class extends Component {
render() {
return (
<InnerComponent {...this.props} />
);
}
}
}
class Rem extends Component { ... }
export default withOOO(Rem);
If this is just a component that uses Rem, not an HOC, then you don't need to create a new class.
const OOO = (props) => {
return <Rem {...props} />;
};
class Rem extends Component { ... }
export default OOO;

I think you used the function wrong, the function OOO returns a class and that class you can use. I have no idea why you would want to do this but here is how you can use the HOC:
//your code in a file called OOO.js
import React, { Component } from 'react';
const OOO = () => {
//you cannot log this.props here, it is not in the class
//console.log(this.props.children)
//I think you have to name the class but I'm not sure
//Have not used classes in React for quite some time
//even React documentation lists a large amount of
//disadvantages using classes and it's only around for
//legacy code
return class MyComponent extends Component {
render() {
//here you can log this.props
//console.log(this.props.children)
return <Rem {...this.props} />;
}
};
};
class Rem extends Component {
render() {
return <p>Helo</p>;
}
}
export default OOO;
//end of the OOO.js file
//here is how you can use it
import CreateComponent from 'OOO.js';
const Component = CreateComponent();
const MyComponent = ()=><Component />
export default MyComponent;

Related

Getting data as a Class Component rather than a Hook

I'm using Auth0, and can grab the data using hooks like so:
const { user } = useAuth0()
How can I refactor and get that same data in a Class Component? I just cannot figure it out or find a good example. I've tried:
this.state = { user: useAuth0()}
But no luck...
auth0-react provides a HOC withAuth0 which you can use with class components as mentioned here
import React, { Component } from 'react';
import { withAuth0 } from '#auth0/auth0-react';
class Profile extends Component {
render() {
// `this.props.auth0` has all the same properties as the `useAuth0` hook
const { user } = this.props.auth0;
return <div>Hello {user.name}</div>;
}
}
export default withAuth0(Profile);
Wrapper function component outside class component;
const AuthWrapper = (E)=> {
const WrapperComponent = (props)=> {
const { user } = useAuth0()
return <E user={user} {...props} />
}
return WrapperComponent;
}
Class Component
#AuthWrapper
class AuthDemo extends Component {
render() {
const { user } = this.props;
...
}
}
you need to use higher order component to implements.
more details: use-with-a-class-component

React JS - Pass Provider components methods to this.children

In React can methods be passed to {this.children} in a container consumer model. What I mean to ask is I have a provider component and I need to pass or refer the provider components methods in the child component.
export default class ContainerCompo extends React.Component {
constructor(props) {
super(props);
this.myHocComponent = null;
}
methodOne() {
//some code
}
methodTwo() {
//some code
}
render() {
return (
{this.props.children}
}
}
export default class InputComponent extends React.Component {
constructor(props) {
super(props);
this.myHocComponent = null;
}
validate() {
ContainerCompo.methodOne(param)
}
render() {
return <InputComponent />
}
// Rendering the components
<ContainerCompo>
<InputComponent containerMethods={methods of ContainerCompo}/>
</ContainerCompo>
I hope my question is clear here, please suggest
First create a react context.
import React, { Component, createContext } from 'react';
// Create's authentication context to be use anywhere in the app
const ContainerContext = createContext();
export default ContainerContext;
Then create a provider for it.
export default class ContainerProvider extends Component {
constructor(props) {
super(props);
this.myHocComponent = null;
}
methodOne() {
//some code
}
methodTwo() {
//some code
}
render() {
const { children } = this.props;
return (
<ContainerContext.Provider
value={{
container: {
methodOne: (...params) => this.methodOne(...params),
methodTwo: (...params) => this.methodTwo(...params)
}
}}
>
{children}
</ContainerContext.Provider>
)}}
Wrap your App with the provider.
import ContainerProvider from './ContainerProvider'
<ContainerProvider>
<App />
</ContainerProvider>
Then create a consumer for the context
export default function withContainer(InComponent) {
return function ContainerComponent(props) {
return (
<ContainerContext.Consumer>
{({ container }) => <InComponent {...props} container={container} />}
</ContainerContext.Consumer>
);
};
}
Then import the consumer and user in your components and you will get the methods as props
import withContainer from './ContainerConsumer'
render() {
const { container } = this.props;
return(<div />)
}
export default withContainer(YourComponent);

React HOC can't resolve import

Hi I am creating my first HOC in react and I have hit a snag. I import a Contentservice inside the class HOC and I have a simple Page class that is wrapped by the WithBackend.
When i navigate to the page component using react Route i get the get the error:
TypeError: Cannot read property 'getPage' of undefined
When i debug the code, i can see the service is available in the constructor but when it gets to the getPage method, i get the alert(id) but then it breaks on the line
this.service.getPage(id);
This is the wrapper function:
import React from "react";
import ContentService from "./ContentService";
const WithBackend = (WrappedComponent) => {
class HOC extends React.Component {
constructor() {
super();
this.service = new ContentService();
}
getPage(id) {
alert(id);
this.service.getPage(id);
}
render() {
return <WrappedComponent getPage={this.getPage} {...this.props} />;
}
}
return HOC;
};
export default WithBackend;
This is the component that is wrapped:
import React, { Component } from "react";
import WithBackend from "./WithBackend";
class PageX extends Component {
render() {
return (
<div>
<h2>Home</h2>
</div>
);
}
componentDidMount() {
this.props.getPage("123");
}
}
const Page = WithBackend(PageX);
export default Page;
This is the ContentService class:
class ContentService {
getPage(id) {
alert(id);
return "Some page";
}
}
export default ContentService;
Can anyone see what i am doing wrong please? Also I am only changing the name of my page to PageX so i can import if after it is being wrapped by the name Page. Is this necessary? I rather just keep the whole thing named page.
I would appreciate your help with this.
Add the following to your code
const WithBackend = (WrappedComponent) => {
class HOC extends React.Component {
constructor() {
super();
this.service = new ContentService();
this.getPage = this.getPage.bind(this) // <-- Add this
}
getPage(id) {
alert(id);
this.service.getPage(id);
}
render() {
return <WrappedComponent getPage={this.getPage} {...this.props} />;
}
}
return HOC;
};
I would also encourage you to read about how this binding works in javascript.
Here is a link to a blog that I liked.
You need to bind this instance to getPage, the recommended way is using arrow function:
getPage = (id) => {
alert(id);
this.service.getPage(id);
}
// Or in constructor
this.getPage = this.getPage.bind(this);
// Or in the event itself
onClick={this.getPage.bind(this)}

reactjs, how to pass props at the class level

This is an example of what im trying to do. I want to pass in props at the MyComponent class, without using <MyComponent hello={'Hello World'}/>, because I am passing MyComponent to some other libraries.
import React, { Component } from 'react';
class MyComponent extends Component {
render() {
const { hello } = this.props;
return (
<div>{hello}</div>
);
}
}
// this line is wrong
MyComponent.props = {
hello: 'Hello World!'
}
<MyComponent />
How is react-redux connect to add this.props.state, and map any other functions to the component's props? I want to inject my custom objects into a component.
You can set default props. I think its a good practice.
import React, { Component } from 'react';
class MyComponent extends Component {
render() {
const { hello } = this.props;
return (
<div>{hello}</div>
);
}headerProp: "Header from props...",
contentProp:"Content from props..."
}
MyComponent.defaultProps = {
hello: 'Hello World!'
}
<MyComponent />
You need to create a Higher Order Component
function withMyObject(WrappedComponent,helloText) {
return class extends React.Component {
render() {
return <WrappedComponent {...this.props} hello={helloText} />;
}
};
}
Usage:
UpdatedComponent = withMyObject(ComponentToBeWrapped,"Hello");

How to avoid writing the same logic in components having a different layout?

How can I avoid writing the same code when two components share some same methods but have a different layout?
The sample components below have a method "renderLastItem" which uses prop "something" passed by the parent components.
I thought about using Higher Order Component Pattern but I'm not sure I I can pass props as an argument to Higher Order Component.
The sample code below is very simple, so in this sample code, I just need to use If statement and change the layout according to the type of components, but in real code, I have more codes and I want to avoid using if statement in order to change the layout according to the type of a component.
How can I avoid writing the same logic in multiple components?
ComponentA
import React, { Component } from 'react';
import PropTypes from 'prop-types';
const propTypes = {};
const defaultProps = {};
class SampleA extends Component {
constructor(props) {
super(props);
}
renderLastItem() {
if(!this.props.something) {
return null;
}
return this.props.something[this.props.something.length - 1];
}
render() {
return (
<div>
<h1>Something</h1>
<p>{this.renderLastItem()}</p>
</div>
);
}
}
SampleA.propTypes = propTypes;
SampleA.defaultProps = defaultProps;
export default SampleA;
ComponentB
import React, { Component } from 'react';
import PropTypes from 'prop-types';
const propTypes = {};
const defaultProps = {};
class SampleB extends Component {
constructor(props) {
super(props);
}
renderLastItem() {
if(!this.props.something) {
return null;
}
return this.props.something[this.props.something.length - 1];
}
render() {
return (
<div>
<ul>
<li>Something</li>
<li>Something else</li>
<li>{this.renderLastItem()}</li>
</ul>
</div>
);
}
}
SampleB.propTypes = propTypes;
SampleB.defaultProps = defaultProps;
export default SampleB;
You absolutely can pass props to a Higher-Order Component! A HOC is simply a function that takes a Component as an argument and returns another Component as a result. So you could create a Higher-Order withLastOfSomething Component just like this:
function withLastOfSomething(Component) {
return function({something, ...otherProps}) {
const item = something ? something[something.length - 1] : null;
return <Component item={item} {...otherProps} />;
}
}
Or with ES6 arrow functions, even more compactly like this:
const withLastOfSomething = (Component) => ({something, ...otherProps}) => {
const item = something ? something[something.length - 1] : null;
return <Component item={item} {...otherProps} />;
}
And then use it like this:
const SampleBWithLastOfSomething = withLastOfSomething(SampleB);
return (<SampleBWithLastOfSomething something={...} />);
You can separate the function that takes the passed props and executes the logic,
export default renderLastItem = (passedProps) => {
if(!passedProps) {
return null;
}
return passedProps [passedProps.length - 1]
}
then import it wherever you need, like this:
import renderLastItem from './somewhere'
export default class SampleA extends Component {
render() {
return (
<div>
<h1>Something</h1>
<p>{renderLastItem(this.props.something)}</p>
</div>
)
}
}

Resources