New to Google AMP pages. Basically, I am trying to access the AMP State to determine whether or not a div should remain hidden:
import React from 'react';
const MyButton = (props) => {
return (
<>
<Head>
<script async src="https://cdn.ampproject.org/v0.js"></script>
</Head>
<div>
<amp-state id="showHiddenContent" show="false"></amp-state>
<button
type="button"
on="tap:AMP.setState({showHiddenContent: { show: !showHiddenContent.show}})"
>
Show More
</button>
<div hidden={!AMP.getState('showHiddenContent').show}>
<p>Show this when the showHiddenContent state evaluates to true</p>
</div>
</div>
</>
);
};
export default MyButton;
I am met with the following error located on the div tag:
'AMP' is not defined
Any thoughts how I can correct this? I've added the script tag in the HEAD of the component but still get the same error. Thanks!
Related
I am using Nextjs 13 with the experimental App Dir but am not sure if this problem I am facing has anything to do with the issue I am facing. I have an id in my home page of "faqs" and when I click on the link, I can see it successfully goes to that link but does nothing in the browser. If I am on another page, I click the link and it takes me to the home page with the correct url but still stays on the top of the page and does not scroll to the indicated id. I did implement scroll={false} as suggested in the documentation but it makes no difference.
Here is a snippet of the relevant code parts:
"use client"
import React, { useState } from "react"
import { useRouter } from "next/navigation"
import Link from "next/link"
const Navigation = () => {
const router = useRouter()
...
In the return:
<Link scroll={false} href="/#faqs">FAQS</Link>
I Even tried:
<button type="button" onClick={() => router.push("/#faqs")}>FAQS</button>
In React the hash works fairly well but in next js, even only in client rendering it seems convoluted. If anyone knows what I am doing wrong or if there is a viable work around, I would sure appreciate it.
Thank you in advance.
If I am missing anything, please let me know.
I use hashtags a lot and I plan to start using the app directory in future projects, so I dug into this and it's not pretty. Apparently, NextJS uses a different package for app directory components client-side called "next/navigation". It's very different from "next/router". Also, when using "next/link" elements, NextJS does not trigger the onRouteChangeComplete event when location.hash changes but location.pathname does not.
So, in order to detect a hash change and scroll to the associated element, I finally had to implement this hack:
"use client"
import { Inter } from '#next/font/google'
import paragraph from './paragraph'
import Link from 'next/link'
import { useEffect, useState } from 'react'
const inter = Inter({ subsets: ['latin'] })
export default function Home() {
const [navClick, setNavClick] = useState(false);
useEffect(() => {
setTimeout(() => {
const hash = window.location.hash;
if (hash) document.querySelector(hash).scrollIntoView();
}, 0);
}, [navClick])
const toggleNavClick = () => setNavClick((oldVal) => !oldVal);
return (
<main>
<nav>
<ul>
<li>
<Link href="/#one" onClick={toggleNavClick}>Section One</Link>
</li>
<li>
<Link href="/#two" onClick={toggleNavClick}>Section Two</Link>
</li>
<li>
<Link href="/#three" onClick={toggleNavClick}>Section Three</Link>
</li>
</ul>
</nav>
<div className="container">
<section id="one">
<h1>Section One</h1>
<div dangerouslySetInnerHTML={{ __html: paragraph }} />
</section>
<section id="two">
<h1>Section Two</h1>
<div dangerouslySetInnerHTML={{ __html: paragraph }} />
</section>
<section id="three">
<h1>Section Three</h1>
<div dangerouslySetInnerHTML={{ __html: paragraph }} />
</section>
</div>
</main>
)
}
Since the hash change cannot be detected because no event is triggered, I basically created an event by toggling navClick each time a link is clicked. The navigation logic is enclosed in setTimeout() function because it triggers after window.location is updated.
Repo: https://github.com/designly1/next-hash-test
Demo: https://next-hash-test.vercel.app/
I am trying to open a PDF in new tab in React JS. The code is attached below. The issue I am having is that my pdf file is having its name altered in the new tab. The tab header becomes sampe.e72672.pdf. I do I just make it sample? Also how do I define a hard coded URL for the new tab?
import React from "react";
import Resume from "../static/sample.pdf";
return (
<div className="MainLandingContainer">
<div className="ResumeContainer">
<Button variant="primary" target="_blank" href={Resume}>
Resume
</Button>
</div>
</div>
);
}
export default Landing;
I think we can't change the baseURL of a window without reloading to a new URL. But we can change the path using history.pushState. Here is a solution which is working in Mozilla and Chrome.
import React from "react";
import Resume from "./Sample.pdf";
const Landing = () => {
const openPDF = () => {
const pdfWindow = window.open("test");
const title = "My PDF";
const URI = "test/test";
const html = `
<html>
<head>
<title>${title}</title>
</head>
<body style="margin:0">
<embed width="100%" height="100%" src=${Resume} type="application/pdf">
</body>
</html>
`;
pdfWindow.document.write(html);
pdfWindow.document.close();
pdfWindow.history.pushState(null, null, URI);
};
return (
<div className="MainLandingContainer">
<div className="ResumeContainer">
<button variant="primary" target="_blank" onClick={openPDF}>
Resume
</button>
</div>
</div>
);
};
export default Landing;
You can find the codesandbox here
I am building a faq page and can't think of a function for this. Basically I have a .json file with questions and answers and I want onClick to toggle the answer that is meant to be hidden and onMouseOut to hide the answer again.
Apreciate your help
import React, {Component} from 'react';
import questionData from '../components/data/faquestions.json';
import PropTypes from 'prop-types';
import '../assets/toggleQue.scss';
const Faq = ({ data }) => {
return(
<div className="grid-faq-container">
<div className="question">
<p><strong> {data.question}</strong> </p>
</div>
<div className="answer">
<p>{data.answer}</p>
</div>
</div>
)
}
const Faqs = () => {
return (
<>
<h1>FAQs</h1>
<div className="faqIteration">
{questionData && questionData.map((e, key) => {
return (
<Faq
data={e}
key={key}
/>
);
})}
</div>
</>
);
};
Faq.propTypes = {
data: PropTypes.object,
};
export default Faqs;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
I don't know if I understood you right.
OnClick you add an identifier for the Question into an array. OnMouseOut you can then check, if the question where your mouse just left is inside this array. If yes, hide it. If no, do nothing. You have to add the onMouseOut listener to every question.
I want to create a basic web application using react. I have implemented creating buttons. I want to redirect to another page on button click. Below is my App.js code
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<p>
<buttontoolbar>
<button const path = '/Components'> Click Me </button>
</buttontoolbar>
</p>
</header>
</div>
);
}
export default App;
When i click on 'click me' button it should redirect to Components.js. Below is the code for Components.js
import React from "react"
function app(){
return(
<p>
Welcome to the world.
</p>
)
}
export default app
Long back i have done these king of things in ASP.NET. there i have used Response.redirect to redirect pages which is so simple. As I am new to React, i know nothing about this. Is there anything like that in React?
Basically React does not have "pages". The idea is more to "show" or "hide" components, this gives the user a page/view impression.
The easiest way to achieve routing in React is to use a declarative router library like react router especially for more complex apps.
Here is an example without react router to understand the basic concept:
const ViewOne = ({onClick}) => (
<div>
View 1 <br />
<button onClick={() => onClick("view2")}>Go to view 2</button>
</div>
);
const ViewTwo = ({onClick}) => (
<div>
View 2 <br />
<button onClick={() => onClick("view1")}>Go to view 1</button>
</div>
);
const App = () => {
const [currentView, setCurrentView] = React.useState("view1");
return (
<div>
{
currentView === "view1" ?
<ViewOne onClick={page => setCurrentView(page)} /> :
<ViewTwo onClick={page => setCurrentView(page)} />
}
</div>
);
};
const domContainer = document.querySelector('#my-app');
ReactDOM.render(<App />, domContainer);
<div id="my-app"></div>
<script src="https://unpkg.com/react#16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js" crossorigin></script>
Use react-router-dom package to define routing and then use one of below mentioned ways on onClick event of button.
this.props.history.push("componentpath").
browserHistory object (in react-router package).
Please refer this Link
try Link component of react-router-dom and pass to as a path to it wherever you want to redirect on onClick.
import { Link } from 'react-router-dom'
and Eg.
<Link to={'/Components'}>
<button > Click Me </button>
</Link>
const {Link, BrowserRouter} = window.ReactRouterDOM
function App(){
return (
<BrowserRouter>
<button><Link to='/abc' target='_blank'> Click Me </Link></button>
</BrowserRouter>
)
}
ReactDOM.render(<App/>, document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>
<body><div id="root"></div></body>
Hi I'm trying to use bootstrap collapse inside a react view and it's not working. It's very simple but I don't understand what's going on.
return (<div>
<button className="btn" type="button" data-toggle="collapse" data-target="#collapseExample" aria-expanded="true" aria-controls="collapseExample">
ButtonClickthis!
</button>
<div className="collapse" id="collapseExample">
<div className="well">
...blablablacontent
</div>
</div>
</div>);
Bootstrap will not work out of the box for react components, since it parses the DOM on load and attaches event listeners etc. You can try something like react-bootstrap or manually triggering inside the componentDidMount lifecycle.
– David
Bootstrap 5 no longer requires jQuery which makes it easier to use with React. For example, here's the Bootstrap Collapse component using the React useState, useEffect hooks:
import { useState, useEffect } from React
import { Collapse } from bootstrap
function CollapseDemo() {
var [toggle, setToggle] = useState(false);
useEffect(() => {
var myCollapse = document.getElementById('collapseTarget')
var bsCollapse = new Collapse(myCollapse, {toggle: false})
toggle ? bsCollapse.show() : bsCollapse.hide()
})
return (
<div className="py-2">
<button className="btn btn-primary" onClick={() => setToggle(toggle => !toggle)}>
Toggle collapse
</button>
<div className="collapse" id="collapseTarget">
This is the collapsible content!
</div>
</div>
)
}
Demo
Figured I'd add an update here. With the updated version of React, not only do you not need vanilla code such as document.getElementById(), but you don't need refs either, or jQuery for that matter. You can simply import collapse like so:
import Collapse from 'react-bootstrap/Collapse'
The collapse transition can be accomplished very easily with this component, as shown in the docs. Here's the code pulled from the same:
const {useState} = React;
const Example = () => {
const [toggle, setToggle] = useState(false);
const toggleFunc = React.useCallback(() => setToggle(!toggle));
return (
<div>
<button onClick={toggleFunc}>Toggle Collapse</button>
<ReactBootstrap.Collapse in={toggle}>
<div>
Stuff to collapse
</div>
</ReactBootstrap.Collapse>
</div>
);
};
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/react-bootstrap#next/dist/react-bootstrap.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div id="react"></div>
** Note: Obviously this code was modified to work with code snippets here on SO. If you're working in your local environment, use the code from the docs, which is even cleaner.
If you don't want to mess around with jQuery:
First, build a ref object for each of your collapsible elements; also build a function to toggle the .show CSS class to the corresponding element.
Then, use toggler function in a button onClick.
class Collapse extends React.Component {
constructor(props) {
super(props)
this.refs = {}
// build ref object with collapsible elements ids
this.setRef = (element) => {
this.refs[element.id] = element
}
// toggle "show" CSS class using plain JS
this.collapseRef = (id) => {
if (this.refs) this.refs[id].classList.toggle('show')
}
}
render() {
return (
<div>
<button
type="button"
onClick={() => this.collapseRef('content1')}
>
Collapse!
</button>
<div
className="collapse"
// Use the `ref` callback to store a reference to the collapsible DOM element
ref={this.setRef}
id="content1"
>
Collapsible content
</div>
</div>
)
}
}
I experienced this before. All you need to do is manually trigger events inside componentDidMount. You might also want to re-triggering the events in the callback of the setState.
Install the module with npm
npm install react-bootstrap bootstrap
And import in your component
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
This work for me