I have a static 2-page Next.js app that I want to integrate a user-based system with. I've decided to use Auth0 for authentication. My goal is to let a user see documents that they have saved on my app, similar to Grammarly, but I am not sure how the entire UI will conditionally change after the user has logged in.
For example, think about the NavBar, which is a component in my app named navbar.js.
import Link from "next/link";
export const siteTitle = "Title";
export const siteDescription = "Description";
export default function Navbar({ page, ...props }) {
return (
<nav className="navbar navbar-expand-lg navbar-light bg-white">
<div className={page == "page1" ? "container-fluid" : "container"}>
{/* <!-- Toggle Open --> */}
{page == "Page1" || (
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarCollapse"
>
</button>
)}
{/* <!-- Collapse --> */}
<div className="collapse navbar-collapse" id="navbarCollapse">
{/* <!-- Toggle Close --> */}
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarCollapse"
>
</button>
{/* <!-- Buttons --> */}
{page == "Page1" ? (
""
) : (
<Link href="/page1">
<a className="navbar-btn">
Page 1
</a>
</Link>
)}
{page == "Link1" ? (
""
) : (
<Link href="https://link2">
<a className="secondary-navbar-btn">
Link 1
</a>
</Link>
)}
</div>
</div>
</nav>
);
}
Considering that the navbar will changing after login, (I want to have "documents" that the user can save directly and later access, meaning that a "My Documents" button must appear in the navbar after login) I am unsure of how the navbar.js file should now be written. Should I just created a new component that will be used after login; if so how would that look? Or should those extra buttons be added in my original navbar.js file, but only rendered after login? Are there existing react hooks that modify components depending on login status?
I would greatly appreciate any links to documentation or tutorials that are solving a problem similar to mine, since I have been unable to find these resources on my own.
Edit 1: If there is anything that I can add/take away/change on this post to make it better please let me know.
Edit 2: I have brain stormed 2 ways of updating the UI in general but I would like to hear some more experienced opinions on my strategies.
Option 1: Update individual components from within the same file after the user logs in. I still don't know what this would look like though.
Option 2: Direct the user to a new page with entirely different components. I won't be able to reuse my existing components and might be repeating code a bit. However I don't mind this option if it is the safer route.
I am open to literally any suggestions at all, just trying to get this thing working
The simplest way is option 2, Auth0 provides hooks that tell you whether there is a user logged in or not and you can use that to conditionally render components. I usually use ternary operators to do that within JSX.
I'd also suggest learning a state management API such as Redux or Context API and then conditionally rendering components based on whether the logged-in state is true or false.
Related
I am new to working on the frontend. I'm learning how to use React and react-router-dom library. The program renders without a problem normally. The problem lies when I try to add a Link component from the React library. When I do this, the DOM is no longer displayed.
import React from "react"
import {Routes, Route, Link} from "react-router-dom"
import Mflix from "./components/mflix.js"
function App(){
return (
<div className="App">
<nav className="navbar navbar-expand navbar-dark bg-dark">
<a href="/mflix" className="navbar-brand"> {/*href links to "/mflix" route */}
Mflix Reviews
</a>
<div className="navbar-nav mr-auto">
<li className="nav-item">
<Link to={"/mflix"} className="nav-link">
Movies
</Link>
</li>
</div>
</nav>
</div>
)
}
This SO forum has a similar problem, except they created a class for their app, and I'm trying to keep it as a function for now.
If I replace the code:
<Link to={"/mflix"} className="nav-link">
Movies
</Link>
with
<a href="/mflix"m className="nav-link">
Movies
</a>
The DOM renders fine, buT I want to use Link because it doesn't force my page to refresh every time.
Edit: I read that instead of passing a JS expression to the to <Link to{"/mflix"}/> I should pass a string <Link to"/mflix"/>. However, the documentation says that if the link uses a path name, then it should be passed to to= as an object, and not a string. IN any case, I tried the suggestion, but the code still returns a blank page.
Edit: This is what the web console has to say about the component:
he above error occurred in the <Link> component:
LinkWithRef#http://localhost:3000/static/js/bundle.js:37314:9
li
div
nav
div
App#http://localhost:3000/static/js/bundle.js:40:72
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
Whenever the DOM disappears, there is an issue in your code. I'm guessing it has to do with this "Mflix" import. Bring up the console and see what it says.
I am using a React functional component with ternary to toggle a show more feature. I would additionally like the following logic: if one of the toggles is true (showing more), then the others are false (not showing). Right now, they just stack on top of each other unless you specifically click the button for each to "off" again.
This is them in initial state:
const [showFirst, setShowFirst] = useState(false)
const [showSecond, setShowSecond] = useState(false)
Here's the login in the render to show one of the 'show mores':
<button
className="btn-show"
onClick={() => setShowFirst(!showFirst)}>
<p className="proj-name">86 List</p>
</button>
Here's how it displays in its proper place:
{showFirst ? (
<div className="hide-me">
<p className="proj-lang">Built with: React.js, Ruby on Rails, Postgresql, CSS</p>
<p className="proj-desc">86List is a community for service-industry professionals to talk about the clients that they serve. Built with Ruby on Rails and React.js, 86List requires login authentication and registration in order to view and interact with co-workers' posts. In future iterations, I want to allow users to create their own accounts and request to be a part of a community with a community leader's approval.</p>
<img className="proj-img" src="/assets/86list.png" alt="" />
<div className="proj-link-container">
<a className="proj-link" href="https://github.com/aawferris/86list" target="_blank" rel="noreferrer" alt="this repo's github">REPO</a>
<a className="proj-link" href="https://86list.netlify.app/" target="_blank" rel="noreferrer" alt="live site for this link">SITE</a>
</div>
</div>
) : (
<div></div>
)}
I have tried making a handleClick that would toggle each back to false and the current one true, but it didn't work. Here's an example:
const handleFirst = () => {
setShowFirst(!showFirst)
setShowSecond(showSecond)
}
Thanks in advance!
Andy
The Idea would be to have an array of objects where you have an attribute like
showMore: true/false and also some sort of an id like id: 1. Each time one of the buttons is clicked, you iterate over the array (which should be a state in the parent component), you set the showMore attribute of that clicked button to true and set all the other ones to false. Then you just set that array as your new State.
Basically I'm trying to remake some simple web page that I have initially created with HTML and CSS to be working rather on React. I managed to redo the page to correctly display when it was moved into React, however I don't really understand why the navigation links that I have on top do not take me to the corresponding section on the same page anymore as well as why the external links to the project sites also stopped working.
Here is the project link code:
import React from "react";
export default function ProjectTile(props) {
return (
<div className="project-tile" id={props.id}>
<a href={props.href} target="_blank" id={props.link_id}>
<img
className="project_screenshot"
src={props.img_src}
alt={props.img_alt}
/>
<p className="project_name">
<span className="brackets"><</span> {props.title}{" "}
<span className="brackets">/></span>
</p>
</a>
</div>
);
}
All props are getting mapped and loaded from the array with corresponding data where each object looks like this:
{
id: "tribute_page",
link_id: "https://codepen.io/konstantinkrumin/full/PooYQbG",
img_src: "https://i.imgur.com/ynRuzOQ.png",
img_alt: "tribute_page_screenshot",
title: "Tribute Page"
}
The navigation links used are the following:
import React from "react";
export default function Navbar() {
return (
<nav id="navbar">
<a className="nav-link" href="#welcome-section">
About
</a>
<a className="nav-link" href="#projects">
Projects
</a>
<a className="nav-link" href="#contact">
Contact
</a>
</nav>
);
}
And each section they refer to have an id corresponding to the href indicated above.
Here if the link to this project on codesandbox
P.S. Everything used to work correctly when it was on HTML.
Also the contact links that seem to be set in similar way as project links are working.
Here are two things I think I found out:
In the ProjectTile.js file, replace href = {props.href} by href={props.link_id and now project opens in codepen.
About the jump link you have made in nav-bar, I think it's because of problem of codesandbox.
If you manage to make your url to https://op6gq.csb.app#projects instead of https://op6gq.csb.app/#projects. That's gonna work.
Or directly visiting https://op6gq.csb.app/#welcome-section jump link too works well.
It looks like there's no href prop. Sounds like what you want is something like
href={`#${props.id}`}
which would evaluate to href="#tribute_page" in this example.
You Have to try that your page url become:
https://op6gq.csb.app#welcome-section
Not:
https://op6gq.csb.app/#welcome-section
please attend to that / in address bar!
For Routing to some page on click, I can achieve it in two ways
import Router from 'next/router'
<button onClick={() => Router.push('/about')}>
<a>Go to About</a>
</button>
And
<button>
Go to About
</button>
Which one is the best practice in Nextjs?
a tag inside button is not allowed in semantic html, both of them are interactive elements.
For links, Next provides Link component that accepts a tag as a child.
For buttons, use <button onClick={() => Router.push('/about')}>text</button> without a.
The best way to create links between pages is to use your nextjs package.
import Link from "next/link";
Then use it like that
<Link href={'/'} params={'id': 1}>
<a>link</a>
</.Link>
if useing node js router href linked by name route
For the best user experience I would suggest a third option / best practice:
import Link from "next/link";
<Link href={"/within/your/page"} passHref>
<button>go</button> // or any other element
</Link>
pre NextJS 10 if your path had dynamic segments you would need to pass "as" also like:
import Link from "next/link";
<Link href={"/review/[id]"} as={"/review/12"} passHref>
<button>go</button> // or any other element
</Link>
The Link Component / the router.push enables client side navigation. This makes navigating your website a lot faster.
you can read more on this here:
https://nextjs.org/docs/api-reference/next/link
https://nextjs.org/docs/api-reference/next/router
From Gatsby's official docs regarding Gatsby's Link component, it states that the Link component is used only for internal links, whereas for external links, one has to use the tag.
I'm building a Button component that has inbuilt props for links. The problem is right now I have to create 2 separate Button components for internal and external links due to the limitation.
My goal is to use one freeLink component that can be used as both internal and external links
I've tried creating a subcomponent (Button) for the button, but I'm unsure of the parent component (freeLink) which requires conditional rendering. The subcomponent is as of follows:
const Button = props => (
<button className={props.btnType}>
<span>{props.text}</span>
</button>
)
This is the visual logic to what I want to achieve:
For Internal links
<freeLink intLink="/about" btnType="btn-cta" text="Read about us">
</freeLink>
...which will render...
<Link to="/about">
<button className="btn-cta">
<span>Read about us</span>
</button>
</Link>
It is relatively similar for external links
<freeLink extLink="https://google.com" btnType="btn-cta" text="Visit Our Partner">
</freeLink>
...which will render...
<a href="https://google.com">
<button className="btn-cta">
<span>Visit Our Partner</span>
</button>
</a>
I'm quite new to Javascript, Gatsby and React so I'm unsure to how to apply a conditional rendering based on props applied.
Any advice, suggestion, or direction to how to code up the freeLink component is greatly appreciated.
P.S: I've seen Conditionally Use Gatsby Link in React Compoment but the chosen answer is too complicated for me to understand, and I don't have enough points to comment to ask for further elaboration.
You could try something simple like this:
const MyLink = (href, text, ...props) => {
if (href.startsWith("http") {
return <a href={href} {...props}>{text}</a>
} else {
return <Link href={href} {...props}>{text}</Link>
}
}
Your component could return different stuff based on weather you pass it a to or a href prop:
import { Link } from "gatsby"
const freeLink = props => {
if (props.to) return <Link {...props} />
return <a {...props} />
}`