React - Replacing a component with another on button click - reactjs

I've two React components, I want a button click in one to replace it entirely with the second.
This is my App Component:
const App = () =>{
const[showMarketing, setShowMarketing] = useState(false);
const[showLanding, setShowLanding] = useState(true)
const toggleViews = () =>{
setShowMarketing(!showMarketing);
setShowLanding(!showLanding);
}
return (
<div>
{showMarketing && <Marketing/>} {showLanding && <Landing toggleViewFn={toggleViews}/> }
</div>
);
}
export default App;
This is the Component that is rendered by default:
const Landing = ({toggleViewFn}) =>(
<div className="shrink-wrapper">
<header className="small-vertical">
<figure className="logo">
<a href="">
<img src={logo} onClick={() => toggleViewFn()}/>
</a>
</figure>
<nav>
</nav>
</header>
</div>
);
This is the component that I want to render on the img click:
const Marketing = () => (
<div>
......Something here
</div>
);
In the current code, the switch happens for a second and the the UI is back to the Landing component. I can't seem to understand why?
I'm new to React, any help appreciated.

The problem is that your <img/> with the onClick is wrapped with an anchor-- when you click the <img/>, the click handler is fired but the anchor click is also registered and the browser navigates. I suspect if you remove the wrapping <a> this will work as expected.
Ultimately, if you are trying to use this for routing, you'd be better off leveraging a library like React Router; while you could try to manage your own routing on your own, it can be complex and is rife with accessibility pitfalls (for instance, using anchors with empty hrefs to wrap items with onClick handlers is not particularly accessible). Hope this helps.

Related

Use <a> tag to scroll down to a differnet component in single page react app

I'm creating a portfolio website using React.
It is a single page website and each section of the website is its own separate component.
My navbar component has links at the top that when clicked I want the page to scroll to the corresponding section further down the page. A traditional About is not working. Do I need to use react-router-dom or am I just missing something?
const App = () => {
return (
<div className='app'>
<Navbar />
<Hero />
<About />
<Projects />
<Footer />
</div>
)
}
export default App
You can use the refs to scroll the page to a section . Refs in react have many applications , you can read details on react official page. Here is an example to use ref for scrolling
const Scroll = () => {
const scrollTo = useRef();
return (
<div>
<button onClick = {()=>{scrollTo.current.scrollIntoView()}></button>
.
.
// Your Other divs
.
.
<div ref={scrollTo}>Scrolled</div>
</div>
);
}
You can use the window.scroll() for scrolling page to a coordinate
window.scroll({top:600,left:50,behavior:'smooth'})
Don't know what I was doing wrong but as Drew suggested in his answer, the classic <a> tag does work as expected.
Go forth and use those tags fellow React devs!

How to NOT render/ hide a React component when no prop is passed?

TLDR: Cannot figure out why component is still being rendered while no props are passed.
So I have been building a NextJS application, and I have this banner component that is shown on every page of my website. It has some header text, buttons and an image:
const Banner = (props) => {
return (
<div className={bannerStyles.wrapper}>
<div className={classnames(bannerStyles.banner, "wrap", "center")}>
<div className={bannerStyles.banner_left}>
<h1>{props.header}</h1>
<div className={bannerStyles.button_wrapper}>
<div className={bannerStyles.button}>
<Button>{props.button || null}</Button>
</div>
<div className={bannerStyles.button}>
<Button>{props.scnd_button || null}</Button>
</div>
</div>
</div>
<div className={bannerStyles.banner_right}>
<Image src={props.image} alt=""></Image>
</div>
</div>
</div>
);
};
Inside of this, as you can see I have two Button components (The MDEast thing is an arrow icon):
const Button = ({children}) => {
return (
<div className={buttonStyles.button}>
<Link href="/"><a>{children} <MdEast /></a></Link>
</div>
)
}
Now I want the option that if no prop is passed, that the Button component(s) do(es) not render/ is hidden from the page, so that it is optional per page. Yet the Button does still render, even though I am not passing any props on my About page. My about page:
const About = () => {
return (
<>
<Banner
header="Hello this is my code"
image={banner_placeholder}
/>
</>
)
}
PS. I am fairly new to React and NextJS, so this might be a beginner mistake, or I am not understanding the fundamentals well enough, but could someone point me in the right direction please?
To conditionally render the button you can use:
props.button && <Button>{props.button}</Button>
When props.button is falsy, then button will not get rendered.

react-scroll Link renders as text and is not clickable - smooth scroll does not work

I am following tutorials online for how to use react-scroll but I cant seem to get it working for me
I am using the Link tag from react-scroll and setting the 'to' attribute to the id of the div I want to scroll to. But when I view the live code the Link I have renders as text and appears to be unclickable.
import { Link } from "react-scroll";
const OpenBlurb = () => {
return (
<div className="blurb-container">
<h1>Welcome</h1>
<Link to="projects" smooth={true} duration={500} offset={50}> My Projects </Link>
</div>
);
};
export default OpenBlurb;
I want the 'My Projects' link to smooth scroll down the page to another component with the id 'projects'
const SecondSection = () => {
return (
<div className="second-container" id="projects" >
<h2>My Projects</h2>
</div>
);
};
export default SecondSection;
Can anyone see what I am doing wrong?
I am guessing "projects" are not identified as an ID.
Have you tried using to="#projects"?
Take a look at these, they might help:
How to scroll to an element?
react-scroll | How to scroll to a specific targeted component when clicking on Navbar Link

How to create a button that opens a new page with the option to return back to previous page [ReactJS

Right below the page you see a 'back to log' button. If someone clicks on that it will return to the left page. So in order to do so I thought using react router will do the job. But not sure how to fix that.Is there someone who can help me to point me to the right direction. Keep in mind that it will not open a new tab!
Link to working snippet to understand the bigger picture of my app. CodeSandBox snippet here
return (
<div>
{info.map((show: any) => {
console.log(show.show)
return (
<div key={show.show.id}>
<ReactMarkdown source={show.show.name}/>
{show.show.image && <img src={show.show.image.medium}/>}
{show.show.genres.map((showGenre: string, index: number) => {
return (
<div key={index}>
<ReactMarkdown source={showGenre}/>
</div>
)
})}
<div>
<Router>
<ul>
<li>
<Link to="/">See deta</Link>
</li>
</ul>
</Router>
</div>
</div>
)
})}
</div>
)
Check out this working example (I placed notes in each file):
https://codesandbox.io/s/modest-panini-hkzlv?file=/src/App.js
Overview:
there are several ways to do this
my suggestion is to use the history npm and create a history.js file
you will also need to use Router from react-router-dom
in your parent component, or in a Context provider, you can store your state
in the parent component, use react-router-dom Switch and Route to place routes
depending on implementation, conditionally render show route for async state update
in your search component, place all your Links using react-router-dom
on click Links should also update app's state of your specific selection
this selection gets passed to the show route/component
in the show component attach an on click that uses history.goBack and resets state
this might help you:
this.props.history.goBack();
it goes back to prev page

The Use of "Navigate(-1)" Fails to Return to Previous Location in Gatsby

I am trying to create a simple "Back" button in Gatsby that returns the the previous page and retains the scroll position. This already happens when using the browser back button, but I'm struggling to produce a custom one. I've read in the Reach Router docs that you can add -1 as an argument to the navigate function to return to previous locations, but It instead throws the number value into the url and gives me a 404. Can someone give me an idea of what I've done wrong? Or if anyone else has managed to make a functional back button for Gatsby projects?
Here is my code-
import React from 'react';
import { graphql, navigate } from 'gatsby'
import Img from "gatsby-image"
import "./design.scss"
const designTemplate = (props) => {
return (
<section className="design">
<div className="design__container">
<h2 className="design__title">
{props.data.design.title}
</h2>
<Img className="design__image" fluid={props.data.design.localImage.childImageSharp.fluid} />
<p className="design__summary">
{props.data.design.summary}
</p>
</div>
<button onClick={navigate(-1)}>Go Back</button>
</section>
);
}
The issue you're having here is just that you didn't define a callback function for your onClick handler.
Instead of this:
<button onClick={navigate(-1)}>Go Back</button>
…you want to do this:
<button onClick={() => { navigate(-1) }}>Go Back</button>
Your onClick must have a callback(arrow function) like this
onClick={()=>{navigate(-1)}}
not
navigate(-1)

Resources