so i try to create a next js website but i notice one things that it not auto refreshing or changing things when i update the component from "component" folder, here is my code on _app.js
import "../styles/globals.css";
import Layout from "../components/Layout";
function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
export default MyApp;
here is my code on component folder "layout.js"
import { useRouter } from "next/router";
import Image from "next/image";
import Link from "next/link";
import styles from "../styles/Home.module.css";
import logo_nabati from "../public/assets/logo-nabati.svg";
export default function Layout({ children }) {
const router = useRouter();
const menuItems = [
{
href: "/",
title: "Homepage",
},
{
href: "/about",
title: "About",
},
{
href: "/contact",
title: "Contact",
},
];
return (
<div className="min-h-screen flex flex-col">
<div className="flex flex-col md:flex-row flex-1">
<aside className="navbar w-full md:w-96">
<div className={styles.logo_nabati}>
<Image
src={logo_nabati}
alt="Nabati Picture"
width={123}
height={75}
/>
</div>
<nav>
<ul>
{menuItems.map(({ href, title }) => (
<li className="m-2" key={title}></li>
))}
</ul>
</nav>
</aside>
<main className="flex-1">{children}</main>
</div>
<style jsx>{`
.navbar {
background-color: #f7d716;
}
`}</style>
</div>
);
}
do i have to configure things again to make it dynamic to changes?
Related
In my next.js app, I stored a hashed token from an OAuth2 provider using cookies. After the user completes the process, they are logged in and the cookie is stored.
This log in button is in a Navbar react component I've made, and is being rendered on every page via _app.js. It includes a conditional rendering system so if the cookie is valid it will not render the log in system. Before I realized that I wasn't going to be able to do what I wanted, I was planning on using getServerSideProps() to do this. However, I realized this is not going to work. How can I go about doing this?
Here's my Navbar.jsx file:
import Link from 'next/link';
import { useRouter } from 'next/router';
import axios from 'axios';
import { doOAuthWork } from '../lib/handleDiscordOAuth2';
function returnLoginInfor(parsed) {
}
const Nav = ({ parsed }) => (
<div className="navbar z-10 top-0 fixed shadow-lg bg-neutral text-neutral-content inset-x-0 bg-opacity-80 backdrop-filter backdrop-blur-lg">
<div className="px-2 mx-2 navbar-start">
<span className="text-lg font-bold">
Status+
</span>
</div>
<div className="hidden px-2 mx-2 navbar-center lg:flex">
<div className="flex items-stretch">
<div className="btn btn-ghost btn-sm rounded-btn">
<Link href="/">
Home
</Link>
</div>
<div className="btn btn-ghost btn-sm rounded-btn">
<Link href="/">
Status
</Link>
</div>
<div className="btn btn-ghost btn-sm rounded-btn">
<Link href="/">
Dashboard
</Link>
</div>
</div>
</div>
<div className="navbar-end">
{doOAuthWork()}
</div>
</div>
);
export default Nav;
(full disclaimer, never finished the function yet)
And here is my _app.js:
import 'tailwindcss/tailwind.css';
import Head from 'next/head';
import { CookiesProvider } from 'react-cookie';
import Nav from '../components/Nav';
import discordOAuth2 from '../lib/handleDiscordOAuth2';
function MyApp({ Component, pageProps }) {
return (
<CookiesProvider>
{' '}
<>
<Head>
<title>Next and MDX Blog</title>
</Head>
<div className="container-fluid mx-auto w-full scrollhost" id="container4">
<Nav> </Nav>
<main className="scrollhost" id="container2">
<Component {...pageProps} />
</main>
</div>
</>
</CookiesProvider>
);
}
export default MyApp;
How should I go about doing this? What is the proper way to do this?
Thanks in advance. :}
(I am a bit of a noob here at react/next so bear with me!)
EDIT: Still having this issue here, I've re-read documentation and not sure what the proper way to go about doing this is.
You can call an api in _appjs itself, and pass it to your components.
The api called in _app.js will be called everytime.
Below is the sample code.
import 'tailwindcss/tailwind.css';
import Head from 'next/head';
import { CookiesProvider } from 'react-cookie';
import Nav from '../components/Nav';
import discordOAuth2 from '../lib/handleDiscordOAuth2';
function MyApp({ Component, pageProps, apiData }) {
return (
<CookiesProvider>
{' '}
<>
<Head>
<title>Next and MDX Blog</title>
</Head>
<div className="container-fluid mx-auto w-full scrollhost" id="container4">
<Nav apiData={apiData}> </Nav>
<main className="scrollhost" id="container2">
<Component {...pageProps} />
</main>
</div>
</>
</CookiesProvider>
);
}
MyApp.getInitialProps = async () => {
const apiData = await getApiData();
return { apiData };
};
export default MyApp
So, Hello My problem is this. I have a C-class Component that is 'maping content' that is located in data.json I will add more content later but, in C class I have a button that is currently pushing me to the Payment page, I want when the button is pressed, that it renders the content(image, price, class) only that content from json into the Payment page where I can style it once again that would be basically it. Thanks in Advance
data.json
[
{
"id":0,
"class":"A-Class",
"Info": "A is the cheapest one ",
"imgA":"./ModImages/Aclass.jpg",
"textA":"fdsd",
"trefuA":"fdsd",
"optionA":"fdsd"
},
{
"id":1,
"imgB":"./ModImages/Bclass.jpg",
"classB":"B-Class",
"priceB":"$46,400",
"textB":"fdsd",
"trefuB":"fdsd",
"optionB":"fdsd"
},
{
"id":2,
"classC":"C-Class",
"imgC":"./ModImages/Cclass.jpg",
"priceC":"$46,400",
"textC":"fdsd",
"trefuC":"fdsd",
"optionc":"fdsd"
}
]
C Class Component
import React from 'react'
import data from './data.json'
import { useHistory } from 'react-router'
function C() {
let history = useHistory();
function handleClick() {
history.push("/payment");
}
return (
<div >
{data.map((postData) =>{
console.log(postData)
return(
<div key=
{postData.id}>
<div className='absolute '>
<button onClick={handleClick}className=' absolute text-black-600 h-10 ml-24 mt-32 bg-white w-
36 rounded-full focus:outline-none focus:ring-2 focus:ring-gray-600'>Buy Now</button>
<img className='w-screen object-contain'src={postData.imgC}></img>
<h1 className='absolute ml-24 md:text-5xl sm:text-5xl top-8'>{postData.classC}</h1>
<h1 className='text-base font-mono absolute ml-24 top-24'>{postData.priceC}</h1>
</div>
</div>
)
})
}
</div>
)
}
export default C
App Component
import React,{useState, useEffect} from 'react'
import './assets/main.css'
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import Header from './Header'
import Home from './Home'
import A from './Models/A'
import B from './Models/B'
import C from './Models/C'
import Payment from './Payment';
function App() {
return (
<div >
<div >
<Router>
<Header />
<Switch>
<Route path="/payment">
<Payment/>
</Route>
<Route path="/C">
<C/>
</Route>
<Route path="/B">
<B />
</Route>
<Route path="/A">
<A />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
</div>
</div>
);
}
export default App;
Home Component
import React from 'react'
import {
BrowserRouter as Router,
NavLink
} from "react-router-dom";
function Home() {
return (
<div className='ml-20'>
<nav className='bg-red-50 max-w-full'>
<ul >
<li>
<Link to="/A">A-Class</Link>
</li>
<li>
<Link to="/B">B-Class</Link>
</li>
<li>
<Link to="/C">C-Class</Link>
</li>
</ul>
</nav>
</div>
)
}
export default Home
You should probably change your route to one with a parameter
<Route path="/payment/:dataId" component={Payment}></Route>
and convert the button to a Link which also passes the id
<Link
to={`/payment/${postData.id}`}
and in the Payment component
also include access to the data.json
get the url parameter from the props
use the provided parameter to find the relevant item in the data
Something like this: https://codesandbox.io/s/festive-spence-bw18s?file=/src/App.js
You can pass additional data with history.push and get it from props in Payment page.
In your C component:
import React from 'react'
import data from './data.json'
import { useHistory } from 'react-router'
function C() {
let history = useHistory();
function handleClick(postData) {
// Pass additional data to Payment component when changing route.
history.push({
pathname: '/payment',
state: {
price: postData.price,
image: postData.image,
class: postData.class
}
});
}
return (
<div >
{data.map((postData) => {
console.log(postData)
return (
<div key=
{postData.id}>
<div className='absolute '>
{/** pass postData to handleClick function */}
<button onClick={() => handleClick(postData)} className=' absolute text-black-600 h-10 ml-24 mt-32 bg-white w-
36 rounded-full focus:outline-none focus:ring-2 focus:ring-gray-600'>Buy Now</button>
<img className='w-screen object-contain' src={postData.imgC}></img>
<h1 className='absolute ml-24 md:text-5xl sm:text-5xl top-8'>{postData.classC}</h1>
<h1 className='text-base font-mono absolute ml-24 top-24'>{postData.priceC}</h1>
</div>
</div>
)
})
}
</div>
)
}
export default C
Inside your Payment component you can pull the price, image and class out this way:
import React from 'react';
import { useLocation } from "react-router-dom";
const Payment = () => {
// ...
const location = useLocation();
console.log(location.state.image) // image url from C
console.log(location.state.class) // class from C
console.log(location.state.price) // price from C
// ...
}
export default Payment;
I'm building an react app where I have a feed component and the feed component consists of array of post components. The post component contains a link in it for viewing the full post component. I'm not able to pass the respective props to the full post component. I'm not able to do a nested route for the fullpost component.
this is my layout component
import React, { Component } from "react";
import Header from "../Header/Header";
import classes from "./Layout.css";
import { Route, Switch } from "react-router-dom";
import FullPost from "../Feed/FullPost/FullPost";
import axios from "axios";
import Feed from "../Feed/Feed";
class Layout extends Component {
state = {
users: [],
};
componentDidMount() {
axios
.get("https://goodwill-60d8a.firebaseio.com/Users.json")
.then((response) => {
this.setState({ users: response.data });
});
}
render() {
console.log(this.state.users);
return (
<div className={classes.main}>
<div>
<Header />
</div>
<div className={classes.content}>
<Switch>
<Route
path="/"
exact
render={() => <Feed users={this.state.users} />}
/>
<Route path="/fullpost" exact render={() => <FullPost />} />
</Switch>
</div>
</div>
);
}
}
export default Layout;
FEED component
import React from "react";
import Post from "./Post/Post";
import classes from "./Feed.css";
const feed = (props) => {
const feedItems = Object.keys(props.users).map((key) => ({
id: key,
...props.users[key],
}));
return (
<div className={classes.feed}>
{feedItems.map((items) => (
<Post
key={items.id}
profilename={items.profileName}
profilepic={items.profilePic}
timestamp={items.timeStamp}
contentimage={items.contentImage}
contenttext={items.contentText}
trend={items.trend}
></Post>
))}
</div>
);
};
export default feed;
Post component
import React from "react";
import classes from "./Post.css";
import ShareButton from "../../UI/ShareButton/ShareButton";
import { Link } from "react-router-dom";
const post = (props) => {
return (
<div className={classes.post}>
<div className={classes.header}>
<div className={classes.profileimage}>
<img className={classes.pic} src={props.profilepic} alt="" />
</div>
<div className={classes.name}>{props.profilename}</div>
<div className={classes.timestamp}>{props.timestamp}</div>
</div>
<div className={classes.container}>
<div className={classes.image}>
<img src={props.contentimage} alt="" />
</div>
<div>
<div className={classes.text}>
<span>{props.contenttext}</span>
</div>
<div className={classes.fullpost}>
<Link to="/fullpost" {...props}>
See Full Post
</Link>
</div>
</div>
</div>
<div className={classes.footer}>
<div className={classes.trend}>
<span>{props.trend}</span>
</div>
<ShareButton />
</div>
</div>
);
};
export default post;
Full Post component
import React from "react";
import classes from "./FullPost.css";
import pic from "../../../Assets/Images/self.jpg";
import { Link } from "react-router-dom";
const fullPost = (props) => {
return (
<div className={classes.fullpost_container}>
<div className={classes.photo_container}>
<img src={props.profilepic} alt=" " />
</div>
<div className={classes.sidebar}>
<div className={classes.profileimage}>
<img src={props.profilePic} alt="" />
</div>
<div className={classes.profilename}>Tony Kroos</div>
<div className={classes.timestamp}>3 Hours Ago</div>
</div>
<div className={classes.feedlink}>
<Link to="/" className={classes.feedlink_text}>
See more posts
</Link>
</div>
</div>
);
};
export default fullPost;
I use client-side routes(HashRouter, Link). In App component i have 3 components - Home, Page1, Page2. And i want to get data from server and on Page1 display this data dynamicaly. But when i go to this page i have error:
When i don't configure Page1 as class and configure it such as const (just as in app.jsx Home component) all work fine, but when i try to configure it like a class, i get this error which i described below.
Here my code:
app.jsx
import React from 'react'
import {
HashRouter as Router,
Route,
Link
} from 'react-router-dom'
import {
Container,
Row,
Col
} from 'react-grid-system';
import Page1 from "./page1.jsx";
const Home = () => (
<div class="container-fixed">
<div class="row">
<div class="col-l-4">
<h2 class="underline">Home</h2>
</div>
</div>
</div>
)
const Subpage = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
)
const Page2 = ({ match }) => (
<div class="container-fixed">
<div class="row">
<div class="col-l-4">
<h2 class="underline">Subpages</h2>
<ul class="content-list">
<li class="content-list-item">
<Link to={`${match.url}/subpage1`}>
subpage1
</Link>
</li>
<li class="content-list-item">
<Link to={`${match.url}/subpage2`}>
subpage2
</Link>
</li>
<li class="content-list-item">
<Link to={`${match.url}/subpage3`}>
subpage3
</Link>
</li>
</ul>
<Route path={`${match.path}/:topicId`} component={Subpage}/>
<Route exact path={match.path} render={() => (
<h3>Please select a subpage.</h3>
)}/>
</div>
</div>
</div>
)
const App = () => (
<Router>
<Container>
<Row>
<Col md={2}>
<h2 class="underline">Menu</h2>
<ul class="content-list">
<li class="content-list-item">
<Link to="/">Home</Link>
</li>
<li class="content-list-item">
<Link to="/page1">Page1</Link>
</li>
<li class="content-list-item">
<Link to="/page2">Page2</Link>
</li>
</ul>
</Col>
<Col>
<Route exact path="/" component={Home}/>
<Route path="/page1" component={Page1}/>
<Route path="/page2" component={Page2}/>
</Col>
</Row>
</Container>
</Router>
)
export default App
page1.jsx
import React, {Component} from 'react';
const Row_ = function(props){
const {id, content} = props;
return (
<div>
id: {id}
content: {content}
</div>
);
}
class Page1 extends React.Component {
constructor(props){
super(props);
this.state = {
datas: [
{id: 14, content: "test"},
{id: 25, content: "test2"},
{id: 75, content: "test3"},
]
};
}
handleClick() {
let fetchedData = gerData();
this.addDataToHTML(fetchedData.id, fetchedData.content);
}
getData() {
fetch('/testdata', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then(results => {
return results.json();
})
}
addDataToHTML(id, content){
const datas = [...this.state.datas,
{value: id, checked: content}
];
this.setState({
datas,
});
}
render(){
<div class="container-fixed">
<div class="row">
<div class="col-l-4">
<h2 class="underline">Page11</h2>
{this.state.datas.map((row, idx) => {
return(
<Row_
id={row.id}
content={row.content}
/>
)
})
}
<button onClick={this.handleClick}>
Get data
</button>
</div>
</div>
</div>
}
}
export default Page1
index.jsx
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import App from "./app.jsx";
import "../t_styles/css/components.min.css";
import "../t_styles/js/components.min.js";
import $ from "jquery";
ReactDOM.render((
<App></App>
), document.getElementById('index'))
1. use className instead of class.
2. add return statement in your render method of Page1 component
render(){
return (<div className="container-fixed">
<div className="row">
<div className="col-l-4">
<h2 className="underline">Page11</h2>
{this.state.datas.map((row, idx) => {
return(
<Row_
id={row.id}
content={row.content}
/>
)
})
}
<button onClick={this.handleClick}>
Get data
</button>
</div>
</div>
</div>)
}
Though I can't see the actual errors, my guess is that your handlers are not bound to the class instance, and therefore you can't access it via this.
So Either bind them to the class (this usually done inside the constructor):
this.handleClick = this.handleClick.bind(this);
this.getData= this.getData.bind(this);
this.addDataToHTML= this.addDataToHTML.bind(this);
Or use an arrow function syntax that will use this in a lexical context:
handleClick = () => {
let fetchedData = gerData();
this.addDataToHTML(fetchedData.id, fetchedData.content);
}
I have a simple app with a home screen, a blog master list, and then blog detail page. Navigating from the home screen to the blog list and back works as expected. When I click on one of the blog posts the app navigates to the page and renders the blog post. But when I go back to the blog master list the blog post is now at the very bottom of the blog list. And if I then navigate back to the home page the same thing, the blog post is in the DOM behind the home page graphic.
I'm using react router 4.1.
Does it have to do with my route setup?
import React, { Component } from 'react'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import NavBar from './components/NavBar'
import Blog from './pages/blog'
import Home from './pages/home'
import Post from './pages/post'
import './css/App.css'
class App extends Component {
render() {
return (
<Router>
<div className="App">
<NavBar />
<Route exact path='/' component={Home} />
<Route path='/blog' component={Blog} />
<Route path='/post/:slug' component={Post} />
</div>
</Router>
)
}
}
export default App
Or with my post component?
import React from 'react'
import fetch from 'isomorphic-unfetch'
import NavBar from '../components/NavBar'
import dateUtils from '../utilities/DateAndTime'
const classNames = require('classnames')
class Post extends React.Component {
constructor(props) {
super(props)
this.state = {
blogObject: null,
fetchBlogObject: false
}
this.fetchBlogObject = this.fetchBlogObject.bind(this)
this.createMarkup = this.createMarkup.bind(this)
this.assignStyleToCoverImage = this.assignStyleToCoverImage.bind(this)
this.formatDateString = this.formatDateString.bind(this)
}
componentWillMount() {
this.fetchBlogObject()
}
componentWillReceiveProps() {
this.fetchBlogObject()
}
fetchBlogObject() {
console.log('fetching')
this.setState({ fetchBlogObject: true })
fetch(`*******************`)
.then(response => response.json())
.then((responseJson) => {
console.log(responseJson)
this.setState({ blogObject: responseJson.object })
})
}
createMarkup(stringToConvertToHtml) {
return { __html: stringToConvertToHtml }
}
assignStyleToCoverImage() {
const style = {
background: `url(${this.state.blogObject.metadata.hero.url})`,
height: '35vh',
backgroundSize: 'cover',
backgroundPosition: 'center'
}
return style
}
formatDateString(dateString) {
console.log(dateString)
const d = `${dateUtils.returnMonthFromISODateString(dateString)} ${dateUtils.returnDateNumberFromISOString(dateString)}, ${dateUtils.returnFullYearFromISOString(dateString)} by Phil Andrews`
return d
}
render() {
const postContainerClasses = classNames({
'post-container': true
})
const postBodyClasses = classNames({
'post-body': true
})
return (
<div>
<NavBar />
{this.state.blogObject ?
<div className={postContainerClasses} >
<div className='header-image' style={this.assignStyleToCoverImage(this.state.blogObject)} />
<div className='post-body-padding'>
<div className='post-header-info'>
<h1 className='post-title'>{this.state.blogObject.title}</h1>
<h4 className='post-date'>{this.formatDateString(this.state.blogObject.created_at)}</h4>
</div>
<div className={postBodyClasses} dangerouslySetInnerHTML={this.createMarkup(this.state.blogObject.content)} />
</div>
</div>
: <div>Loading...</div>
}
</div>
)
}
}
export default Post
Or with my blog list button action for navigating to a post page?
<Link id={this.props.blogObject.slug} to={`/post/${this.props.blogObject.slug}`}>
<button className='blog-button' style={buttonStyle} id={this.props.blogObject.slug} />
</Link>
I'm not sure why it would continue to render the entire component but if I get rid of the <NavBar /> in the post component the issue goes away.
Not working:
return (
<div>
<NavBar />
{this.state.blogObject ?
<div className={postContainerClasses} >
<div className='header-image' style={this.assignStyleToCoverImage(this.state.blogObject)} />
<div className='post-body-padding'>
<div className='post-header-info'>
<h1 className='post-title'>{this.state.blogObject.title}</h1>
<h4 className='post-date'>{this.formatDateString(this.state.blogObject.created_at)}</h4>
</div>
<div className={postBodyClasses} dangerouslySetInnerHTML={this.createMarkup(this.state.blogObject.content)} />
</div>
</div>
: <div>Loading...</div>
}
</div>
)
Working:
return (
<div>
{this.state.blogObject ?
<div className={postContainerClasses} >
<div className='header-image' style={this.assignStyleToCoverImage(this.state.blogObject)} />
<div className='post-body-padding'>
<div className='post-header-info'>
<h1 className='post-title'>{this.state.blogObject.title}</h1>
<h4 className='post-date'>{this.formatDateString(this.state.blogObject.created_at)}</h4>
</div>
<div className={postBodyClasses} dangerouslySetInnerHTML={this.createMarkup(this.state.blogObject.content)} />
</div>
</div>
: <div>Loading...</div>
}
</div>
)