How to write a HOC in react which takes another hoc? - javascript

I am learning material UI by myself and came across this HOC pattern method withStyle HOC API, i tried implementing by myself with simple style(just string) to understand how this hoc(withStyle) function takes this hoc(named HigherOrderComponent)function works in code.
this is App.js and rendering<App/> this in index.js
import React from 'react';
import customWithStyle from './customWithStyle';
import Button from '#material-ui/core/Button';
function HigherOrderComponent(props) {
return <Button color={props}>Higher-order component</Button>;
}
const someStyle="primary";
export default customWithStyle(someStyle)(HigherOrderComponent);
And the code i tried writing is in customWithStyle.js file
import React from 'react'
const customWithStyle=(style)=>(Hoc)=>{
//console.log(style);
console.log(<Hoc/>)
return <Hoc props={style}/>
}
export default customWithStyle ;
i am getting error
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
can some one help.

The only way that i use Hoc was with class. Something like this will help you
function HigherOrderComponent(props) {
return (<div style={{color: props.color}}>this is the main component</div>)
}
const customWithStyle = style => WrappedComponent => {
class HOC extends React.Component{
render = () => (<WrappedComponent color={style}></WrappedComponent>);
}
return HOC;
};
const StyledComponent = customWithStyle("red")(HigherOrderComponent);
ReactDOM.render(<StyledComponent />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Use props.props within your HigherOrderComponent functional component for value of color attribute in Button Material component

Related

inherit class react in razor page

i have a razor page and i want to render a class React.Component inside it. If i render a single page it works but if i import in the App class a Child component throw me the following error:
Warning: React.createElement: type is invalid -- expected a string
(for built-in components) or a class/function (for composite
components) but got: object. You likely forgot to export your
component from the file it's defined in, or you might have mixed up
default and named imports.
Uncaught Invariant Violation: Element type is invalid: expected a
string (for built-in components) or a class/function (for composite
components) but got: object.
What did i miss to import Child correctly?Or i have to change React.createElement in order to have a class that is modularized?
[EDIT] i just found out that i cannot use React.createElement for scripts that are module...so how can i do the same thing??
App.jsx:
import { Child } from './Components/Child';
class App extends React.Component{
componentDidMount() {
}
render() {
console.log(this.props)
const list = this.props.Property1;
return (
<div>
<ul>
{list.map(item => (
<li key={item.name}>{item.name}</li>
))}
</ul>
<Child></Child>
</div>
);
}
}
Child.jsx
export class Child extends React.Component {
componentDidMount() {
}
render() {
return (
<div>
Sono il figlio del component padre : {this.props.data}
</div>
);
}
}
Index.cshtml:
#using Newtonsoft.Json;
#using SportData.Web.Models;
#using System.Web.Optimization;
#model SportContainer
<div id="App">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
<script src="#Url.Content("~/js/app.jsx")" type="module" ></script>
<script src="#Url.Content("~/js/Components/Child.jsx")" type="module"></script>
<script>
var modelObject = #Html.Raw(Json.Serialize(Model.sportList));
ReactDOM.render(
React.createElement(App, { Property1: modelObject }),
document.getElementById("App")
);
</script>
The issue seems to be with the export statement in the Child.jsx component. You're using export class Child, but in your App.jsx component you're importing the component using import { Child } from './Components/Child';.
Try changing the import statement in App.jsx to
import Child from './Components/Child';
In this case, you would only need to specify the default export (in this case Child) without curly braces.

Export React component to be used in a JSX tag

The Goal:
Replace the default burger icon of react-burger-menu with an icon from react-icons-kit. Example from the former's docs:
<Menu customBurgerIcon={ <img src="img/icon.svg" /> } />
However, I'd like to have a module of icons and import from that. So the above example would be something like <Menu customBurgerIcon={MenuIcon} />.
The Problem:
I get an error saying: "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined."
I'm exporting my icon like this:
// Icons.js
import React from 'react';
import { Icon } from 'react-icons-kit';
import { menu } from 'react-icons-kit/icomoon/menu';
export const MenuIcon = () => <Icon icon={menu} />;
And using it like this:
// Menu.js
import React from 'react';
import { slide as BurgerMenu } from 'react-burger-menu';
import { MenuIcon } from './Icons';
// ...
class Menu extends React.Component {
// ...
render() {
return (
<BurgerMenu
isOpen={open}
onStateChange={state => this.handleStateChange(state)}
customBurgerIcon={MenuIcon}
>
// ...
);
}
}
If I do the imports from react-icons-kit directly in Menu.js and write customBurgerIcon={<Icon icon={menu} />} it works. I suppose there must be something wrong with the way I'm trying to export the icon component.
How to fix this? Thank you in advance!
try
return (
<BurgerMenu
isOpen={open}
onStateChange={state => this.handleStateChange(state)}
customBurgerIcon={<MenuIcon />}
>
in Menu.js

How can pass a props to a variable?

I'm trying "hydrate" props from elements to child components that will render. The problem is that I can't figure out how I can do it with my configuration.
I have seen this answer, I tried to adapt it, but so far I'm getting errors (see bottom).
For a bit of background, I'm developing a Rails based application that uses React for the front end. So I don't use React router or such, it just "displays" the datas.
Here is how I set everything up:
front.js (where everything gets rendered)
import React from 'react';
import ReactDOM from 'react-dom';
import extractActionName from './lib/extractActionName';
import {elementForActionName} from './lib/elementForActionName';
import 'jquery';
import 'popper.js';
import 'bootstrap';
let actionName = extractActionName();
let value = "value";
let renderElement = function (Element, id) {
ReactDOM.render(
<Element value={value} />,
document.getElementById(id)
);
};
renderElement(elementForActionName[actionName], actionName);
lib/elementForActionName.js
import React from 'react';
import Homeindex from '../home/home';
import Contact from '../home/contact';
// This files create an associative array with id React will be
// looking for as a key and the component as value
export const elementForActionName = {
'index': <Homeindex />,
'contact': <Contact/>,
};
lib/extractActionName.js
export default function extractActionName() {
// The body contains classes such as "home index", so
// I return the "action name" of my controller (home) to
// front.js so I will render the good component
return document.body.className.split(' ').pop();
}
home/home.js
import React from 'react';
import Header from '../layout/header';
import Footer from '../layout/footer';
export default class homeIndex extends React.Component {
render() {
return(
<div>
<Header/>
<h1>Hello this will be the content of the landing page hello</h1>
<Footer/>
</div>
)
}
}
My problem is that I'd like to make an Ajax call in my "front.js" file, then transmit the received data (here, "value"). The error I'm getting is the following:
Uncaught Error: Element type is invalid: expected a string (for
built-in components) or a class/function (for composite components)
but got: object.
I'm lacking experience with React, how can I resolve this problem?
Thank you in advance.
You are currently returning the instance of a component:
export const elementForActionName = {
'index': <Homeindex />, <--- here
'contact': <Contact/>,
};
And then attempting to instantiate it again:
let renderElement = function (Element, id) {
ReactDOM.render(
<Element value={value} />, // <--- here
document.getElementById(id)
);
};
Instead, just use the component class:
export const elementForActionName = {
'index': Homeindex,
'contact': Contact,
};

Understanding React Higher-Order Components

Can someone please explain Higher-order components in React. I have read and re-read the documentation but cannot seem to get a better understanding. According to the documentation, HOCs help remove duplication by creating a primary function that returns a react component, by passing arguments to that function.
I have a few questions on that.
If HOCs create a new enhanced component, can it be possible not to pass in any component as argument at all?
In an example such as this, which is the higher order component, the Button or the EnhancedButton.
I tried creating one HOC like this:
// createSetup.js
import React from 'react';
export default function createSetup(options) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.testFunction = this.testFunction.bind(this);
}
testFunction() {
console.log("This is a test function");
}
render() {
return <p>{options.name}</p>
}
}
}
// main.js
import React from 'react';
import {render} from 'react-dom';
import createSetup from './createSetup';
render((<div>{() => createSetup({name: 'name'})}</div>),
document.getElementById('root'););
Running this does not show the HOC, only the div
Can anyone help out with a better example than the ones given?
A HOC is a function that takes a Component as one of its parameters and enhances that component in some way.
If HOCs create a new enhanced component, can it be possible not to pass in any component as argument at all?
Nope, then it wouldn't be a HOC, because one of the conditions is that they take a component as one of the arguments and they return a new Component that has some added functionality.
In an example such as this, which is the higher order component, the Button or the EnhancedButton.
EnhanceButton is the HOC and FinalButton is the enhanced component.
I tried creating one HOC like this: ... Running this does not show the HOC, only the div
That's because your createSetup function is not a HOC... It's a function that returns a component, yes, but it does not take a component as an argument in order to enhance it.
Let's see an example of a basic HOC:
const renderWhen = (condition, Component) =>
props => condition(props)
? <Component {...props} />
: null
);
And you could use it like this:
const EnhancedLink = renderWhen(({invisible}) => !invisible, 'a');
Now your EnhancedLink will be like a a component but if you pass the property invisible set to true it won't render... So we have enhanced the default behaviour of the a component and you could do that with any other component.
In many cases HOC functions are curried and the Component arg goes last... Like this:
const renderWhen = condition => Component =>
props => condition(props)
? <Component {...props} />
: null
);
Like the connect function of react-redux... That makes composition easier. Have a look at recompose.
In short, If you assume functions are analogues to Components, Closure is analogous to HOC.
Try your createSetup.js with:
const createSetup = options => <p>{options.name}</p>;
and your main.js
const comp = createSetup({ name: 'name' });
render((<div>{comp}</div>),
document.getElementById('root'));
A higher-order component (HOC) is an advanced technique in React for reusing component logic. Concretely, a higher-order component is a function that takes a component and returns a new component.
A HOC is a pure function with zero side-effects.
Example: CONDITIONALLY RENDER COMPONENTS
Suppose we have a component that needs to be rendered only when a user is authenticated — it is a protected component. We can create a HOC named WithAuth() to wrap that protected component, and then do a check in the HOC that will render only that particular component if the user has been authenticated.
A basic withAuth() HOC, according to the example above, can be written as follows:
// withAuth.js
import React from "react";
export function withAuth(Component) {
return class AuthenticatedComponent extends React.Component {
isAuthenticated() {
return this.props.isAuthenticated;
}
/**
* Render
*/
render() {
const loginErrorMessage = (
<div>
Please login in order to view this part of the application.
</div>
);
return (
<div>
{ this.isAuthenticated === true ? <Component {...this.props} /> : loginErrorMessage }
</div>
);
}
};
}
export default withAuth;
The code above is a HOC named withAuth. It basically takes a component and returns a new component, named AuthenticatedComponent, that checks whether the user is authenticated. If the user is not authenticated, it returns the loginErrorMessage component; if the user is authenticated, it returns the wrapped component.
Note: this.props.isAuthenticated has to be set from your application’s
logic. (Or else use react-redux to retrieve it from the global state.)
To make use of our HOC in a protected component, we’d use it like so:
// MyProtectedComponent.js
import React from "react";
import {withAuth} from "./withAuth.js";
export class MyProectedComponent extends React.Component {
/**
* Render
*/
render() {
return (
<div>
This is only viewable by authenticated users.
</div>
);
}
}
// Now wrap MyPrivateComponent with the requireAuthentication function
export default withAuth(MyPrivateComponent);
Here, we create a component that is viewable only by users who are authenticated. We wrap that component in our withAuth HOC to protect the component from users who are not authenticated.
Source
// HIGHER ORDER COMPOENTS IN REACT
// Higher order components are JavaScript functions used for adding
// additional functionalities to the existing component.
// file 1: hoc.js (will write our higher order component logic) -- code start -->
const messageCheckHOC = (OriginalComponent) => {
// OriginalComponent is component passed to HOC
const NewComponent = (props) => {
// business logic of HOC
if (!props.isAllowedToView) {
return <b> Not Allowed To View The MSG </b>;
}
// here we can pass the props to component
return <OriginalComponent {...props} />;
};
// returning new Component with updated Props and UI
return NewComponent;
};
export default messageCheckHOC;
// file 1: hoc.js -- code end -->
// file 2: message.js -- code start -->
// this is the basic component we are wrapping with HOC
// to check the permission isAllowedToView msg if not display fallback UI
import messageCheckHOC from "./hoc";
const MSG = ({ name, msg }) => {
return (
<h3>
{name} - {msg}
</h3>
);
};
export default messageCheckHOC(MSG);
// file 2: message.js -- code end -->
// file 3 : App.js -- code start --->
import MSG from "./message.js";
export default function App() {
return (
<div className="App">
<h3>HOC COMPONENTS </h3>
<MSG name="Mac" msg="Heyy !!! " isAllowedToView={true} />
<MSG name="Robin" msg="Hello ! " isAllowedToView={true} />
<MSG name="Eyann" msg="How are you" isAllowedToView={false} />
</div>
);
}
// file 3 : App.js -- code end --->

Newbie to React => Element type is invalid: expected a string

I am going around in circles with the following when trying to load the basics of a React app into the browser.
Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: undefined.
The code is as follows (test.tsx)
/// <reference path="./typings/tsd.d.ts" />
import * as React from "react";
import * as ReactDOM from 'react-dom'
ReactDOM.render(
<TodoApp name="jim"/>, document.getElementById('root')
);
class TodoApp extends React.Component<any, any>{
constructor(props) {super(props); this.state = {};}
render() {
return (
<div>
<button>hit me</button>
</div>
)
}
}
export default TodoApp;
test.html
<html>
<body>
<div id="root"></div>
<script src="./bundle.js"></script>
</body>
</html>
the tsx is complied and bundled with Browserify and the error is occuring in the bundle.js
specifically # instantiateReactComponent(node) & the invariant function
Many thanks in advance !!
You're calling render and passing in a component before you have defined it.
// won't work!
var person = new Person() <-- undefined
class Person {}
// will work
class Person {}
var person = new Person()
Classes do not get 'hoisted' like functions do.

Categories

Resources