next js - how to create hoc for the page - javascript

When I use the code below, I've got the error
Error: The default export is not a React Component in page: "/"
pages/index.tsx
import React, { useState, useRef } from "react";
import type { NextPage } from "next";
import WithToast from "hoc/WithToast/WithToast";
const Home: NextPage = () => {
return (
<div>
Home
</div>
);
};
export default WithToast(Home);
WithToast.tsx
import React from "react";
import { ToastContainer, Zoom } from "react-toastify";
import { NextComponentType, NextPageContext } from "next";
function WithToast(Component: NextComponentType<NextPageContext, any, {}>) {
return (
<div className="with-toast">
<ToastContainer
transition={Zoom}
position="top-center"
autoClose={200}
hideProgressBar={true}
draggable={false}
closeButton={false}
/>
{Component}
</div>
);
}
export default WithToast;

You should call the wrapped Component like this:
function withToast(Component: NextComponentType<NextPageContext, any, {}>) {
return (
<div className="with-toast">
<ToastContainer
transition={Zoom}
position="top-center"
autoClose={200}
hideProgressBar={true}
draggable={false}
closeButton={false}
/>
<Component />
</div>
);
}
or like this:
function withToast(component: NextComponentType<NextPageContext, any, {}>) {
return (
<div className="with-toast">
<ToastContainer
transition={Zoom}
position="top-center"
autoClose={200}
hideProgressBar={true}
draggable={false}
closeButton={false}
/>
{component()}
</div>
);
}
Or you are basically trying to render a function object in JSX as a child, and that throws an exception.
The HOC names should not begin with a capital case character.
That NextJS error should just be due to the fact you had that error that was not catched during SS render.

Related

Unable to integrate a React ErrorBoundary

I have an ErrorBoundary class (ErrorBoundry.jsx) that looks like this:-
import React, { Component } from 'react'
import ErrorPage from '../../ErrorPage'
const WithErrorBoundary = ({ renderError } = {}) => {
return WrappedComponent => {
return class ErrorBoundary extends Component {
state = { error: null }
componentDidCatch(error, errorInfo) {
this.setState({ error })
}
render() {
if (this.state.error) {
return <ErrorPage />
}
return <WrappedComponent {...this.props} />
}
}
}
}
export default WithErrorBoundary;
The fallback UI (ErrorPage) looks like this:-
import React from 'react';
import { useTranslation } from 'react-i18next';
import classNames from 'classnames';
import Logo from '../../../../../images/logo.svg';
import styles from './styles.module.css';
export default function ErrorPage(props) {
const { t } = useTranslation('common');
return (
<>
<div className={classNames('navbar', 'navbar-fixed-top', styles.headerSection)}>
<div className={classNames('col-md-12', 'col-xs-12' , styles.logoSection)}>
<span className={styles.logo}>
<img className='img-fluid' src={Logo} alt='Logo' />
</span>
</div>
</div>
<div className={styles.content}>
<div className={styles.unavailableDiv}>
<h1>{t('unavailable_page_title')}</h1>
<p>{t('unavailable_page_message_1')}</p>
<p>{t('unavailable_page_message_2')}</p>
</div>
</div>
</>
);
};
I am wrapping my routes in app.jsx with the ErrorBoundary like this:-
const ErrorBoundary = lazy(() => import('./components/core/ErrorBoundary/ErrorBoundry'));
<ErrorBoundary>
<Switch>
<Redirect from='/' to='/notfound' exact />
<Redirect from='/:country/ord' to='/notfound' exact />
<Route path='/notfound' component={NotFound} />
<PrivateRoute path='/:country/' exact component={Payment} />
<PrivateRoute path='/:country/:encryptedParams' exact component={DetailPage} />
<Route component={NotFound} />
</Switch>
</ErrorBoundary>
When I run my app, I get a blank page with a console error:-
Warning: 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.
I went through the answers in Functions are not valid as a React child. This may happen if you return a Component instead of from render, but they didn't quite help me. Where exactly am I going wrong?

Error "Unexpected character '�'. (1:0)" when creact a higher order component in react

I'm beginner in react.js.
I'm tring to create my own higher order component.
But I have a problem.
enter image description here
my code:
withState.jsx:
import React from "react";
export function withState(component) {
const C = component;
return function (props) {
return <C {...props} extraProp="withState() is runing..." />;
};
}
Component file (Header.jsx):
import React from "react";
import { withState } from "./../HOFs/withState";
function Header(props) {
return (
<>
<h2>Header</h2>
<p>{JSON.stringify(props)}</p>
</>
);
}
export default withState(Header);

Make component draggable using react-dnd

I'm trying to drag a component using react-dnd
I would try to make like this example but only dragging for the moment.
In my app on top of all component I import react-dnd-html5-backend and wrap my app:
import Backend from 'react-dnd-html5-backend'
import { DndProvider } from 'react-dnd'
render(
<Provider store={store}>
<FluentuiProvider theme={themes.teams}>
<DndProvider backend={Backend}>
<App theme={themes.teams} />
</DndProvider>
</FluentuiProvider>
</Provider>,
document.getElementById('root')
)
Then in my component:
import { useDrag } from 'react-dnd';
export default ({ call, pauseCall, onHoldCalls, endCall, addNote }) => {
const [collectedProps, drag] = useDrag({
item: { type: 'Personna' },
})
return (
<div className="personna">
<Persona ref={drag} {...call.CALL_DETAILS.personInfos["formattedPersData"]} size={PersonaSize.size40} />
</div>
)
}
When I render the component I get this error
TypeError: node.setAttribute is not a function
at HTML5Backend.connectDragSource (HTML5Backend.js:487)
at SourceConnector.reconnectDragSource (SourceConnector.js:115)
I haven't added a dragSource because in example it's not used.
I don't know why I'm getting this error message.
As #Panther said, the ref should be placed on a HTML element, not a React Component:
return <div ref={drag}>{"Drag me!"}</div>;
Or, in your case, you could add the ref to the <div className="personna"> container:
return (
<div ref={drag} className="personna">
<Persona ....
To help you get to the minimal drag example, take a look at this very minimal setup:
App.js
import React from "react";
import Backend from "react-dnd-html5-backend";
import { DndProvider } from "react-dnd";
import { MyComponent } from "./MyComponent";
import "./styles.css";
export default function App() {
return (
<DndProvider backend={Backend}>
<div className="App">
<MyComponent />
</div>
</DndProvider>
);
}
MyComponent.js
export default function App() {
return (
<DndProvider backend={Backend}>
<div className="App">
<MyComponent />
</div>
</DndProvider>
);
}
Try it on codesandbox.io!

How do I change the innerHTML of an element using React?

I want to change innerHTML of a div, when I click on the button. I don't know why, but instead of getting an error, or getting the expected result it deletes to content and replacing it with "[object Object]".
How can I get it work?
import React from 'react';
import Login from './components/login.js';
import SignIn from './components/signin';
import './App.css';
function App() {
function LoginOnClick(){
document.getElementById("wrapper").innerHTML = <SignIn />;
}
return (
<div className="container" id="wrapper">
<button onClick={LoginOnClick}>Login</button>
<Login />
</div>
);
}
export default App;
You can make use of Hooks (Added n React 16.8).
import React, {useState} from 'react';
import Login from './components/login.js';
import SignIn from './components/signin';
import './App.css';
function App() {
const [signIn, setSignIn] = useState(false);
return (
<div className="container" id="wrapper">
{signIn ? <SignIn /> : <> //This is React Fragments syntax
<button onClick={() => setSignIn(true)}>Login</button>
<Login />
</>
}
</div>
);
}
export default App;
With react you don’t have to set the innerHtml to do this, instead the more typical way is to have internal state in your component and conditionally render your SignIn component based off that. To use state the component either needs to be class or use hooks, classes are more traditional so I changed the component to be a class.
To make a class a react component you need to extend the class with the React.Component, this is because react components have lots of internal behaviours that you need to include with your class for it to be considered a component.
So
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
signIn: false,
};
this.LoginOnClick = () => {
this.setState({ signIn: true });
};
}
render() {
if (this.state.signIn) {
return (
<div className="container">
<SignIn />
</div>
);
}
return (
<div className=“container”>
<button onClick={this.LoginOnClick}>Login</button>
<Login />
</div>
);
}
}
Here is a simple way to do it:
import {useState} from "react";
const App = () => {
const [txt, setTxt] = useState("");
setTxt(<p> 'Lorem ipsum dummy text blabla.' </p>);
return(
<div>
{txt}
</div>
)
}
export default App;

React Router: TypeError: render is not a function

Im working on this app and when I run npm start I keep getting this error "TypeError: render is not a function". Ive tired everything from deleting the dependencies to running npm install. I even update react-router-dom and react-dom several times. Im at a lost here.
Here is the GitHub to the repository
https://github.com/Drayz/My-Book-Reads-App.git
Here is the Code:
index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
import "./index.css";
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
); enter code here
App.js:
import React from 'react'
import { Switch,Route } from 'react-router-dom'
import Homepage from './windows/Homepage'
import Search from './windows/Search'
import Provider, {MyContext} from './Provider/'
import './App.css'
class BooksApp extends React.Component {
render() {
return (
<div className="app">
<Provider>
<MyContext.Consumer>
context
<Switch>
<Route exact path={"/"} render={ () => (
<MyContext.Consumer>
{context => <Homepage {...context} />}
</MyContext.Consumer>
)}/>
<Route exact path={"/search"} render={ () => (
<MyContext.Consumer>
{context => <Search {...context} />}
</MyContext.Consumer>
)}/>
</Switch>
</MyContext.Consumer>
</Provider>
</div>
)
}
}
export default BooksApp
Provider/index.js:
import React, { Component } from 'react';
export const MyContext = React.createContext();
export default class index extends Component {
constructor() {
super();
this.state ={
books:[],
currentlyReading:[],
wantToRead:[],
read:[],
addBooks: books => {
const currentlyReading = books.filter(book => book.shelf === 'currentlyReading');
const read = books.filter(book => book.shelf === 'read');
const wantToRead = books.filter(book => book.shelf ==='wantToRead');
this.setState({ books, currentlyReading, read, wantToRead });
},
moveBook: (book, newShelf, allShelfs) => {
console.log(newShelf);
const newBooks = this.state.books.map(allBooks => {
const foundID = allShelfs[newShelf].find(
bookID => bookID === allBooks.id
);
if (foundID) {
allBooks.shelf = newShelf;
}
return allBooks;
});
this.state.addBooks(newBooks);
}
};
}
render() {
return (
<MyContext.Provider value={{...this.state}}>
{this.props.children}
</MyContext.Provider>
)
}
}
SearchBook.js
import React, {Component} from 'react';
import {Link} from 'react-router-dom'
export default class Searchbooks extends Component {
render() {
return (
<div className="open-search">
<Link to={'/search'}>
Add a book
</Link>
</div>
)
}
}
Bookshelf.js
import React, {Component} from 'react';
import Book from './Book';
export default class Bookshelf extends Component {
render() {
return (
<div className="bookshelf">
<h2 className="bookshelf-title">{this.props.title}</h2>
<div className="bookshelf-books">
<ol className="books-grid">
{this.props.books &&
this.props.books.map(book => <Book key={book.id} {...book} moveBook={this.props.moveBook} />)}
</ol>
</div>
</div>
)
}
}
Book.js
import React, {Component} from "react";
import {update} from '../BooksAPI'
export default class Book extends Component {
handleChange = async e => {
e.presist()
try {
const shelf = e.target.value;
const book = this.props;
const result = await update(book, shelf);
this.props.moveBook(book, shelf, result);
} catch (error) {
console.log(error)
}
};
render() {
return (
<li>
<div className="book">
<div className="book-top">
<div className="book-cover"
style={{
width: 128,
height: 193,
backgroundImage:`url(${this.props.imageLinks ? this.props.imagesLinks.thumnail : ''})`
}}
/>
<div className="book-shelf-changer">
<select onChange={this.handleChange} value={this.props.shelf}>
<option value="move" disabled>Move to...</option>
<option value="currentlyReading">Currently Reading</option>
<option value="wantToRead">Want to Read</option>
<option value="read">Read</option>
<option value="none">None</option>
</select>
</div>
</div>
<div className="book-title">{this.props.title}</div>
<div className="book-authors">{this.props.authors ? this.props.author[0] : 'No Author'}</div>
</div>
</li>
)
}
}
Local_Host_Error, Local_Host_Error, Local_Host_Error
In App.js your consumer just says "context". I think what you meant was for that to be the variable that holds the data that comes from the provider. Right now it's just being read as a string and the render function freaks out because... well the logging isn't very good. In short when the component goes to render it hits a whole bunch of undefined and freaks out.
To fix this use:
{ context => {Your switch statement }}

Categories

Resources