I have created a next js project with normal javaScript.This is my 404 page
404.js
import { useEffect } from "react";
import { useRouter } from "next/router";
import Link from "next/link";
export default function NotFound() {
const router = useRouter();
useEffect(() => {
setTimeout(() => {
// router.go(1)
router.push("/");
}, 3000);
}, []);
return (
<div className="not-found">
<h1>Oooops!!!</h1>
<p>
Go back to home page
<Link href="/">
<a>Home page</a>
</Link>
</p>
</div>
);
}
Then I created a seperate type script based next js project.
404.tsx
// import type { NextPage } from 'next'
import Link from "next/link";
const NotFound = () => {
return (
<div>
<h2>Oh no!</h2>
<p>There is not much left here for you</p>
{/* <Link href="/">
<a >Visit our home page</a>
</Link> */}
</div>
);
};
export default NotFound;
This is what I get in the typescript project.
What is wrong in the 404.tsx file?
It says that client_dev_noop_js module loading failed. There is nothing with 404.tsx, however, it is better to name _error.js and _error.tsx
Related
Im trying to simply have a shared variable between my pages in my Next.Js application.. My _app.js below contains the following..
import { useState } from 'react';
const CustomApp = ({ Component, pageProps }) => {
// Variables
const [testVariable, setTestVariable] = useState(0)
// globalFunctions
const setTestVariable = (newValue) => setLocalVariable(newValue);
return (
<Component
{...pageProps}
// Export Variables
testVariable={testVariable}
// Export Functions
setTestVariable={setTestVariable}
/>
);
}
export default CustomApp
I have two pages... Both are the same except one is called index.js and exports Home, the other is called about.js and exports About...
import { useState, useEffect } from 'react'
import 'bulma/css/bulma.css'
import styles from '../styles/Home.module.css'
const Home = ({ testVariable, setTestVariable, }) => {
useEffect(() => {
})
return (
<div id={styles.outerDiv}>
<Head>
<title>My Next.Js Page</title>
<meta name="description" content="A Next.js application" />
</Head>
<div id={styles.navBar}>
<a href="/" id={styles.navLink}>
<h3>Home</h3>
</a>
<a href="/about.js" id={styles.navLink}>
<h3>About</h3>
</a>
</div>
<div id={styles.content} className="content">
<br/>
<h2>Test Variable: {testVariable}</h2>
<button id={styles.incrementButton} onClick={setTestVariable(1)}>Set Test Variable to 1</button>
</div>
</div>
)
}
export default Home
When I tap the button the variable on my page changes to 1, however when I switch pages the variable goes back to 0. I also receive no errors of any sort. All feedback is greatly appreciated! Thanks for your time.
The variable goes back to 0 because you are using a tags wich "reloads" the page
To navigate you should use the Link component that is built in next.
This Link component prevents the default behavior of reload the page and you can keep your state while navigate on the page
I am using hook router 1.2.5 and I have a very simple home page as below:
import { useRoutes } from "hookrouter";
import React from "react";
import Nav from "./pages/Nav";
import AboutPage from "./pages/About";
const HomePage = () => {
const routeResult = useRoutes({
"/about": () => <AboutPage />
});
return (
<div fluid>
<div xs={3} md={1} lg={1} className="nav-container">
<Nav />
</div>
<div xs={9} md={11} lg={11}>
{routeResult || <AboutPage />}
</div>
</div>
);
};
export default HomePage;
But when I run lint, I see below warnings show up.
8:10 warning Component definition is missing display name react/display-name
8:10 warning Declare only one React component per file react/no-multi-comp
I know I can disable these eslint warnings. But I would like to know how to fix them. For example, I don't have another component in my file. So why would it show react/no-multi-comp warning, or did I miss something? Any helps are appreciated.
UPDATE
I was able to fix react/display-name by replacing the arrow function as below:
const routeResult = useRoutes({
"/about"() {
return <AboutPage />;
}
});
I'm trying to learn Next-JS, and I'm making a small, experimental project to familiarize myself. However, something seems to be going wrong with the Link tag. It does redirect to the friends page specified, but for some reason, the page content remains the same as it is on home. And clicking the test link while on this page, it attempts to redirect not to "#", but to "friends#".
Is there something I'm not understanding here? Any help would be appreciated. Here is my conde:
index.tsx:
import Link from 'next/link';
import styles from '../styles/Home.module.css'
const HomePage = () => {
// const handleClick = (e: Event) => {
// e.preventDefault()
// router.push('./friends')
// alert(router)
return (
<div className={styles.div}>
<h1 className={styles.h1}>WELCOME TO HOME PAGE</h1>
<ul className={styles.ul}>
<li className={styles.li}>
<Link href='/friends'>
<a>FRIENDS</a>
</Link>
</li>
<li className={styles.li}>
<Link href="#">
<a>TEST</a>
</Link>
</li>
</ul>
</div>
)
}
export default HomePage
friends.tsx:
import Link from 'next/link'
const Friends = () => {
return (
<div>
<h1>WELCOME TO FRIENDS</h1>
<Link href="/">
RETURN TO HOME
</Link>
</div>
)
}
export default Friends;
_app.tsx:
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import HomePage from '../pages/index'
function MyApp({ Component, pageProps }: AppProps) {
return <HomePage />
}
export default MyApp
Screentshots of what I'm seeing are listed below. Note the URLs.
Home page
Friends page
After clicking the Test link, for which the href is currently "#"
You're seeing the same page on all links is because you're always displaying the same component, which is <Homepage />. Instead, you need to render the component with pageProps to display the correct page according to the url.
The updated code of the _App component should be something like, where you need to display the Component available through the props.
import '../styles/globals.css'
import type { AppProps } from 'next/app'
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
export default MyApp
Please also take a look at the docs of the Next.js regarding the custom _app, to see available options/features out of the box.
From docs: The Component prop is the active page, so whenever you navigate between routes, Component will change to the new page. Therefore, any props you send to Component will be received by the page.
pageProps is an object with the initial props that were preloaded for your page by one of our data fetching methods, otherwise it's an empty object.
I am creating a website where I have a pdf viewer inside my page imported dynamically.
the code runs locally without errors, but during the "npm run build" command I find the following error:
> Build error occurred
ReferenceError: window is not defined
at Object.<anonymous> (C:\Users\GustavoMorilla\MyProfile\node_modules\#pdftron\webviewer\webviewer.min.js:1:224)
at Object.g7Pv (C:\Users\Gustavo Morilla\MyProfile\.next\server\pages\resume\viewer.js:121:18)
at __webpack_require__ (C:\Users\Gustavo Morilla\MyProfile\.next\server\pages\resume\viewer.js:23:31)
at Module.vRHl (C:\Users\Gustavo Morilla\MyProfile\.next\server\pages\resume\viewer.js:134:76) {
type: 'ReferenceError'
info - Collecting page data .npm ERR! code ELIFECYCLE }
viewer.js code:
import React, { useRef, useEffect } from "react";
import WebViewer from "#pdftron/webviewer";
const Viewer = () => {
const viewer = useRef(null);
useEffect(() => {
WebViewer(
{
path: '/lib',
initialDoc: "/pdf/GustavoMorilla.pdf",
},
viewer.current
).then(function (instance) {
instance.setTheme("dark");
});
}, []);
return (
<div>
<div className="Viewer">
<div className="header flex justify-between">
<a>Resume</a>
<a className="text-sm">You can download the file on "Settings" button</a>
</div>
<div className="Webviewer" ref={viewer}></div>
</div>
</div>
);
};
export default Viewer;
resume.js code:
import SiteLayout from "../../components/SiteLayout";
import React from "react";
import dynamic from "next/dynamic";
const Viewer = dynamic(() => import("../resume/viewer.js"), { ssr: false });
export default function Resume({ resume }) {
return (
<div>
<SiteLayout>
<div className="main w-screen">
<Viewer />
</div>
</SiteLayout>
</div>
);
}
should be something related with the SSR or lifecycle... i dont know.
window object doesn't exist on the server side, use conditional rendering to solve the problem.
import SiteLayout from '../../components/SiteLayout'
import React from 'react'
import dynamic from 'next/dynamic'
const Viewer = dynamic(() => import('../resume/viewer.js'), { ssr: false })
export default function Resume({ resume }) {
return window ? (
<div>
<SiteLayout>
<div className="main w-screen">
<Viewer />
</div>
</SiteLayout>
</div>
) : null
}
This is a basic header component that includes buttons to show login/register forms on click.
The intention is, of course, that the login and register components shouldn't be loaded until requested.
react-loadable is creating an additional file ( 0.js ) that seem to include the register component, but my search did not turn out any reference to login.
In any case, upon initial load, both login and register are being loaded, as my console.log shows.
Of course, I was expecting that they would not be loaded until the triggering button was clicked on.
Note that I did attempt to use react-loadable on routes, and it seems to work correctly, ie, I can see the files being loaded on the network tab of the dev tools.
Also, I happen to have a service worker precaching the build files for now, but I do not believe that should impact this. Or should it? It doesn't on routes.
Excerpts of the header component:
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { withRouter } from 'react-router-dom';
import Loadable from 'react-loadable';
//import Register from '../register/'; ** PREVIOUS REGULAR IMPORT
//import Login from '../login/'; ** PREVIOUS REGULAR IMPORT
import { Loading } from '../../../tools/functions';
const Login = Loadable({
loader: () => import('../login/'),
loading: Loading,
delay: 200,
timeout: 5000
});
const Register = Loadable({
loader: () => import('../register/'),
loading: Loading,
delay: 200,
timeout: 10000
});
render () {
return (
<header>
<div className="header_top flex">
<div className="branding"></div>
<div className="header_spacer"></div>
<Status handleClick={this.handleLoginRegisterClick}/>
</div>
<Nav />
<div className="auth">
<Register
active={this.state.activeRegister}
handleClick={this.handleLoginRegisterClick}
toggleDialog={this.toggleLoginRegisterDialogs}
/>
<Login
active={this.state.activeLogin}
handleClick={this.handleLoginRegisterClick}
handleClickPasswordReset={this.togglePasswordResetRequest}
toggleDialog={this.toggleLoginRegisterDialogs}
/>
<PasswordResetRequest
active={this.state.activePasswordResetRequest}
hidePasswordResetRequest={this.togglePasswordResetRequest}
/>
<SessionHandler location={location}/>
</div>
{showAdForm()}
</header>
);
}
The Loading function:
export const Loading = ({ error }) => {
if (error) {
return 'error';
} else {
return <h3>Loading...</h3>;
}
}
My mistake was that I had the state change on the child component.
So, I factored it up, changing the render method of the header component as follows:
const activeDialog = () => {
if (this.state.activeLogin) {
return (
<Login
active={this.state.activeLogin}
handleClick={this.handleLoginRegisterClick}
handleClickPasswordReset={this.togglePasswordResetRequest}
toggleDialog={this.toggleLoginRegisterDialogs}
/>
)
} else if (this.state.activeRegister) {
return (
<Register
active={this.state.activeRegister}
handleClick={this.handleLoginRegisterClick}
toggleDialog={this.toggleLoginRegisterDialogs}
/>
)
} else if (this.state.activePasswordResetRequest) {
return (
<PasswordResetRequest
active={this.state.activePasswordResetRequest}
hidePasswordResetRequest={this.togglePasswordResetRequest}
/>
)
}
}
return (
<header>
<div className="header_top flex">
<div className="branding"></div>
<div className="header_spacer"></div>
<Status handleClick={this.handleLoginRegisterClick}/>
</div>
<Nav />
<div className="auth">
{activeDialog()}
<SessionHandler location={location}/>
</div>
{showAdForm()}
</header>
);