React and React Router - A really very basic and simple Cookie Banner - javascript

I'm working on React applications. I need a really very simple Cookie banner. The one that informs that the website uses cookies. There are various (theoretically simple) solutions in npm packages, but they all cause some problems in my projects. I have the impression that they are overdesigned, although they are supposed to be simple.
My projects mainly based on React with React Router.

OK. We have React and React Router (react-router-dom). And we need:
react-cookie npm install react-cookie
react-modal npm install react-modal
bootstrap npm install bootstrap
ModalCookies.js component:
import React from 'react';
import {
Link
} from 'react-router-dom';
import { useCookies } from "react-cookie";
import Modal from 'react-modal';
import '../modal.css';
function ModalCookies() {
const [cookies, setCookie] = useCookies(["allowcookies"]);
function handleCookie() {
setCookie("allowcookies", true, { path: "/", expires: new Date(Date.now() + (100 * 24 * 60 * 60 * 1000)) });
}
function closeModal() {
handleCookie();
}
return (
<Modal isOpen={cookies.allowcookies ? false : true} className="Modal" overlayClassName="Overlay">
<h6>PRIVACY & COOKIES POLICY</h6>
<p className="text-justify">
I use cookies to personalize content, ads and to analyze the traffic.
I also share information about your use of my website with my social media,
advertising and analytics partners who may combine it with other information that you have provided to them or that they have collected from your use of their services.
If you continue browsing, it means that you accept the use of cookies on this website.
</p>
<div className="text-right">
<button
className="btn btn-secondary mr-2 mb-2"
onClick={closeModal}>
OK
</button>
<Link to="/privacy"
className="btn btn-outline-secondary mb-2"
onClick={closeModal}>
Learn More
</Link>
</div>
</Modal>
);
}
export default ModalCookies;
modal.css file:
.Modal {
position: absolute;
top: auto;
left: 15%;
right: 15%;
bottom: 15%;
border: 1px solid rgb(100, 100, 100);
background: rgb(255, 255, 255);
outline: none;
padding: 40px;
z-index: 1;
}
.Overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(255, 255, 255, 0.60);
}
The file that manages the main view of the application with React Router (for example: Home.js or App.js)(excerpt):
//...
import ModalCookies from './ModalCookies';
//...
</Route>
</Switch>
<ModalCookies />
<Footer />
</Router>
//...
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { CookiesProvider } from 'react-cookie';
import Modal from 'react-modal';
import App from './App';
import 'bootstrap/dist/css/bootstrap.css';
Modal.setAppElement('#root');
ReactDOM.render(
<React.StrictMode>
<CookiesProvider>
<App />
</CookiesProvider>
</React.StrictMode>,
document.getElementById('root')
);
It works very well in my projects. Any comments or questions are welcome.

Related

The CSS for my navigation bar component is no working and instead is taking the CSS of my log in component

I am creating a website that utilizes the Spotify API and I have created a login page where the user can login through Spotify and if they successfully login they are redirected to my home page. I have CSS for the login that puts the login button in the center of the page and when they get redirected to the homepage I am trying to put the navigation bar on top of the page but for some reason, it takes the CSS of the Login component and ignores all the CSS I try to put in for the navigation bar component and I want to know why that is.
my App.js file:
import React, { useState, useEffect} from 'react';
import { Route, Routes } from 'react-router-dom';
import { Container } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import Login from './components/Login';
import Home from './components/Home';
import NavBar from './components/NavBar';
import Guesser from './components/Guesser';
import Feed from './components/Feed';
import Generator from './components/Generator';
const code = new URLSearchParams(window.location.search).get('code')
const App = () => {
return (
<div className='main-content'>
<Container>
{code ?
<div>
<Routes>
<Route path='/' element={<NavBar />}>
<Route index element={<Home />} />
<Route path='/guesser' element={<Guesser />} />
<Route path='/feed' element={<Feed />} />
<Route path='/generator' element={<Generator />} />
</Route>
</Routes>
</div> :
<Login />}
</Container>
</div>
)
}
export default App
my App.css file:
.main-content{
display: flex;
height: 100vh;
width: 100%;
background-color: black;
color:white;
padding: 0;
}
My Login.js File:
import React from 'react'
import {Button} from 'react-bootstrap';
import "./index.css"
import SpotifyLogo from '../../spotify-logo2.png';
const Login = () => {
const authEndPoint = "https://accounts.spotify.com/authorize";
const clientId = "{My client id}";
const redirectUri = "http://localhost:3000";
const scopes = [
"streaming",
"user-read-email",
"user-read-private",
"user-library-read",
"user-library-modify",
"user-read-playback-state",
"user-modify-playback-state"
];
const AUTH_URL = `${authEndPoint}?client_id=${clientId}&response_type=code&redirect_uri=${redirectUri}&scope=${scopes.join("%20")}`;
return(
<div className="main-content">
<div className='spot-img'>
<img src={SpotifyLogo} alt='Spotify Logo'/>
</div>
<Button
href={AUTH_URL}
className='button'
>
login
</Button>
</div>
)
}
export default Login
My Login.css File:
.main-content{
align-items: center;
justify-content: center;
display:flex;
flex-direction: column;
position: relative;
}
.spot-img{
position: absolute;
top: 100px;
}
.button{
background-color: green;
width: 100px;
}
My Navbar.js File:
import "./index.css";
import { NavLink, Outlet } from 'react-router-dom';
const NavBar = () => {
return(
<div className='main-content'>
<nav >
<NavLink
exact='true'
activeclassname='active'
to='/'
>
Home
</NavLink> |
<NavLink
exact='true'
activeclassname='active'
to='/guesser'
>
Guesser
</NavLink> |
<NavLink
exact='true'
activeclassname='active'
to='/feed'
>
Feed
</NavLink> |
<NavLink
exact='true'
activeclassname='active'
to='/Generator'
>
Generator
</NavLink> |
</nav>
<Outlet />
</div>
)
}
export default NavBar;
My NavBar.css File:
.nagivation{
position: absolute;
top: 10px;
background-color: gray;
}
All the other component file are simple and only output the name of the webpage and have no CSS filed in yet.
Login image
Home page after successfully logging in
The problem is that you are reusing the same CSS for the logo and the navbar. The parent div of both the logo and the navbar uses the .main-content which centers everything
.main-content{
align-items: center;
justify-content: center;
display:flex;
flex-direction: column;
position: relative;
}
I suggest you use different styling for the parent div of your navbar.

React components not rendering when routing to new page with react-router-dom v6

I am trying to set up routing in my React app. I am not getting any error and the app is not breaking but when I navigate to a new page nothing is displayed. I am using react-router-dom v6 and 'Switch' has been replaced with 'Routes' and component has been replaced with element: https://reacttraining.com/blog/react-router-v6-pre/. It also appears you do not need the leading "/".
EDIT at bottom of page.
http://localhost:3000/Player and http://localhost:3000/* (or anything other than the * ) both render blank screens.
This is the landing page which works fine:
HomePage.tsx
/** #jsxImportSource #emotion/react */
import React from 'react';
import { css } from '#emotion/react';
import logo from '../assets/cyberpunk.png';
export const HomePage = () => (
<div
css={css`
margin: 10px auto 20px auto;
padding: 30px 20px;
max-width: 1000px;
display: flex;
align-items: center;
justify-content: space-between;
`}
>
<div>
<img
src={logo}
alt="Logo"
css={css`
width: 700px;
margin-left: 130px;
`}
/>
<h2>Players</h2>
<button>Select a toon</button>
</div>
</div>
);
This is the player page:
PlayerPage.tsx
import React from 'react';
export const PlayerPage = () => <h2>"One toon"</h2>;
The page not found page:
NotFoundPage.tsx
import React from 'react';
export const NotFoundPage = () => <h2>"Page Not Found"</h2>;
Finally,
App.tsx
/** #jsxImportSource #emotion/react */
import React from 'react';
import { css } from '#emotion/react';
import { Header } from './header';
import { HomePage } from './Views/HomePage';
import { fontFamily, fontSize, gray2 } from './Styles';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { PlayerPage } from './Views/PlayerPage';
import { PlayersPage } from './Views/PlayersPage';
import { PlayerCreatePage } from './Views/PlayerCreatePage';
import { NotFoundPage } from './Views/NotFoundPage';
function App() {
return (
<BrowserRouter>
<div
css={css`
font-family: ${fontFamily};
font-size: ${fontSize};
color: ${gray2};
`}
>
<Header />
<Routes>
<Route path="" element={<HomePage />} />
<Route path="Players" element={<PlayersPage />} />
<Route path="Player" element={<PlayerPage />} />
<Route path="Create" element={<PlayerCreatePage />} />
<Route path="*" element={<NotFoundPage />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
Why would the h2 elements in the NotFoundPage and PlayerPage not be being displayed? It acts like I'm navigating to an incorrect route every time.
I fixed it kind of. I remade one of the pages to look like this:
function PlayerCreatePage() {
return (
<div style={{ padding: 20 }}>
<h2>About View</h2>
<p>Lorem ipsum dolor sit amet, consectetur adip.</p>
</div>
);
}
export default PlayerCreatePage;
And this one does show up. Why is that? What is wrong with the other views?
I tried to recreate your error but was unable to. At first, I thought it might be an issue with you not writing return() inside the functions but then I realised you have exported without curly braces, so return isn't necessary. Anyway, the code runs fine, you should have tried to recreate in a new environment. Peace!
Issue is in the App.tsx file, change the element prop to component, move the generic route to the bottom and add exact
in front of specific routes.
see the below changes :- `
/** #jsxImportSource #emotion/react */
import React from 'react';
import { css } from '#emotion/react';
import { Header } from './header';
import { HomePage } from './Views/HomePage';
import { fontFamily, fontSize, gray2 } from './Styles';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { PlayerPage } from './Views/PlayerPage';
import { PlayersPage } from './Views/PlayersPage';
import { PlayerCreatePage } from './Views/PlayerCreatePage';
import { NotFoundPage } from './Views/NotFoundPage';
function App() {
return (
<BrowserRouter>
<div
css={css`
font-family: ${fontFamily};
font-size: ${fontSize};
color: ${gray2};
`}
>
<Header />
<Routes>
<Route exact path="/Players" component={<PlayersPage />} />
<Route exact path="/Player" component={<PlayerPage />} />
<Route exact path="/Create" component={<PlayerCreatePage />} />
<Route path="/" component={<HomePage />} />
<Route path="*" component={<NotFoundPage />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
`
it will work.

Next.js Flashing with Ant Design on Chrome

I am currently developing a website utilizing Next.js and Ant Design and I have found a Chrome only issue that I am unable to fix. Whenever the user leaves the page or leaves the chrome window and returns, there is a brief flash of black on every page of the website. Furthermore, it seems that CSS styles are not being loaded fast enough, because when the website is reloaded, it is possible to see an enlarged version of my SVG logo before it is properly resized, which is very distracting. These issues only persist on Chrome to my knowledge as I have tested it with Safari and Firefox and have been unable to reproduce this issue. I have looked around for a solution, but they all use styled-components as well as a _document.js file in their project to solve the issue, but I have neither currently. Any help would be great on this, the relevant code will be below, if anything else is needed I can provide more. (Not every bit is used, I did use a tutorial to set learn how next.js worked so there are remnants of that).
EDIT: I want to add that the css flash/black flash happens on refresh of the page or when the window is deselected or minimized. I am still unsure if this is a problem with Next.js or if it is a problem with my implementation of the global css file with Ant Design.
EDIT 2: This problem is still an issue and I have been still unable to fix it...It's not too serious but it is annoying for chrome users I have found when doing alpha testing.
_app.js
import '../styles/global.css'
import React from 'react'
import App from 'next/app'
import Head from 'next/head'
import { Provider } from '../contexts/countryContext'
//There is a chrome only issue where the CSS Elements flash for like half a second when the page is loaded, not sure how to fix.
export default class MyApp extends App {
render() {
const { Component, pageProps } = this.props;
return (
<div>
<Head>
</Head>
<Provider>
<Component {...pageProps} />
</Provider>
</div>
)
}
}
global.css
#import '~antd/dist/antd.css';
:root {
--primary-color: #8497f5;
--light-secondary: #A0AAEC;
--light-tertiary: #5467DE;
--dark-secondary: #474C69;
--dark-tertiary: #4554B5;
}
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
line-height: 1.6;
font-size: 18px;
}
* {
box-sizing: border-box;
}
a {
color: #0070f3;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
img {
max-width: 100%;
display: block;
}
index.js
import {Layout, Row, Spin, Divider} from 'antd'
import {Component, useState, useContext} from 'react'
import Link from 'next/link'
import {Context} from '../contexts/countryContext'
import layout from '../styles/layout.module.css'
import utils from '../styles/utils.module.css'
import SiteHeader from '../components/siteHeader'
import CalculationCard from '../components/CalculationCard'
import CookieHeader from '../components/CookieHeader'
const { Header, Content, Sider, Footer } = Layout;
const Main = () => {
const context = useContext(Context)
return (
<Layout style={{backgroundColor:"white"}}>
<SiteHeader/>
<Content className={layout.container}>
<header className={layout.header}>
<Link href="countrySelector">
<img src={context.flag + ".png"} className={layout.headerImage}/>
</Link>
<h1 className={utils.heading2Xl}>{context.name}</h1>
</header>
<CookieHeader/>
</Content>
<Content>
<Row gutter={16}>
<Divider orientation="left" style={{fontSize: "1.15rem", lineHeight: 0}}>Economic</Divider>
<CalculationCard name={"Maintenance"} desc={"Land and Naval Mintenance"} img={"local_reg_cost_icon"} link="maintenance"/>
<CalculationCard name={"Development Cost"} desc={"Mana Costs for Development"} img={"dev_cost"}/>
</Row>
</Content>
{/* <Footer style={{height: "100%"}}>
Indev
</Footer> */}
</Layout>
);
}
export default Main;

React: styles being imported to wrong module unexpectedly

Im new to React JS, working on my first soon-to-be live site. I have styled input in a form in a seperate component, then imported the styles to that component. After implementing routing, it seems that this
style is applied to forms across the site, whether or not i import them. Note, i was initially putting all
styles in index.css until I expanded the scope of the site, and this was no longer practical. It now seems
that the index.css styles remain, even after i removed the styles im trying to get rid of from index.css. Either that, or there is something wrong with my routing, importing, exporting, that im not seeing, which is causing this bug:
This style is being applied from a different component with its own imported stylesheet.
I want the sign up form to appear like a normal form input, but its hidden because of the styles
applied to BrowsePhotos.js. I am completely unsure why this happens.
here is my project directory tree
and here is some source code related to possible problem sources
src/components/auth/SignUp.js
import React, { useState } from 'react'
import './auth.css';
const SignUp = () => {
return(
<form onSubmit={handleSubmit} className="App-sign-up">
<label className="auth-field"> Email:
<input onChange={handleEmailChange} type="text"/>
{ !emailError && <div className="error">{emailError}</div>}
</label>
<label className="auth-field"> Password:
<input onChange={handlePasswordChange} type="password"/>
{ !passwordError && <div className="error">{passwordError}</div>}
{/* should also define errors for the other offenders- length, expected characters */}
</label>
{ password &&
<label className="auth-field"> Password:
<input onChange={handleConfirmPasswordChange} type="password"/>
{ !confirmPasswordError && <div className="error">{confirmPasswordError}</div>}
{ password !== confirmPassword && <div className="error">Password and Confirm Password must match</div> }
</label>
}
<button type="submit">Create Account</button>
<div>Already have an account? Sign In!</div>
</form>
)
}
export default SignUp;
src/components/photos/UploadForm.js
import React, { useState } from 'react';
import ProgressBar from './ProgressBar';
import './UploadForm.css'
// TODO: add a new controlled component for providing text to use
// as photo description/ alt text.
const UploadForm = () => {
//equivalent to setting state to '' in class based component
const [file, setFile] = useState(null);
// const [description, setDescription] = useState(null);
const [error, setError] = useState(null);
const handleChange = event => {
// reference to the selected file,
// and a list of allowable image types
const selected = event.target.files[0]
const types = ['image/png','image/jpeg']
if (selected && types.includes(selected.type)) {
setFile(selected);
setError('');
// if (event.target.type === 'textarea') {
// console.log("we got a description")
// }
} else {
setFile(null);
setError('Enter a valid photo type : jpg or png')
}
}
return (
<form>
<label>
<span>+</span>
<input onChange={handleChange} type="file"/>
{/* <div className="description">
<label className="inner-label">Description of the uploaded file</label>
<textarea cols="30" rows="10"
onChange={handleChange}
></textarea>
</div> */}
</label>
<div className="output">
{ error && <div className="error" >{ error }</div>}
{ file && <ProgressBar file={file} setFile={setFile}/>}
</div>
</form>
);
}
export default UploadForm;
src/components/photos/UploadForm.css
form{
margin: 30px auto 10px;
text-align: center;
}
label input{
height: 0;
width: 0;
opacity: 0;
}
label{
display: block;
width: 30px;
height: 30px;
border: 1px solid var(--primary);
border-radius: 50%;
margin: 10px auto;
line-height: 30px;
color: var(--primary);
font-weight: bold;
font-size: 24px;
}
label:hover{
background: var(--primary);
color: white;
}
.output{
height: 60px;
font-size: 0.8rem;
}
.error{
color: var(--error);
}
src/index.css
#import url('https://fonts.googleapis.com/css2?family=Noto+Serif:wght#400;700&display=swap');
:root{
--primary: #efb6b2;
--secondary: #4e4e4e;
--error: #ff4a4a;
}
/* base styles & title */
body{
font-family: "Noto Serif";
color: var(--secondary);
}
.App{
max-width: 960px;
margin: 0 auto;
}
.title h1{
color: var(--primary);
font-size: 1.2rem;
letter-spacing: 2px;
font-weight: normal;
}
src/components/general/title // note: home of routing, ive tried commenting out BrowsePhotos from routing. this is then imported to app.js
import React from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import './general.css'
import About from '../general/About';
import SignIn from '../auth/SignIn';
import SignUp from '../auth/SignUp';
import BrowsePhotos from '../photo/BrowsePhotos';
import BrowseProfiles from '../auth/BrowseProfiles';
const Title = () => {
return (
<div className="title">
<Router>
<nav style={{padding: "5px"}}>
<h1 className="title">Oral-History</h1>
<h1>
<Link to="/about">About</Link>
</h1>
<h1>
<Link to="/sign-in">Sign In</Link>
{/* becomes sign-out when user is signed in */}
</h1>
<h1>
<Link to="/sign-up">Sign Up</Link>
{/* sign-up becomes 'my profile' after sign in */}
</h1>
<h1>
<Link to="/profiles">Profiles</Link>
</h1>
<h1>
<Link to="/photos">All Photos</Link>
</h1>
</nav>
<Route exact path="/about" component={About}/>
<Route exact path="/sign-in" component={SignIn}/>
<Route exact path="/sign-up" component={SignUp}/>
<Route exact path="/profiles" component={BrowseProfiles}/>
<Route exact path="/photos" component={BrowsePhotos}/>
</Router>
</div>
)
}
export default Title;
I've also tried redefining the rule set for label and label input within SignUp.css, to set all the properties to default, or inherits: false, with no luck there.
It sounds like the CSS is not being imported scoped but globally. You could use a CSS-in-JS library like CSS-Modules or react-scoped-css to fix this.
Another way would be to give the html-elements classes and not style them directly. That is usually more scalable.

React Loading in Stylesheet only when Component is loaded

I have an App Component that does all my routing for my project, where I import all the necessary components.
import React from "react";
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import './App.scss';
import Login from "../../login/Login";
import Overview from "../../overview/Overview";
import SubNav from "../../subnav/SubNav";
import ForgotPassword from "../../forgot-password/ForgotPassword";
const App = () => {
return (
<div className="App">
<Router>
<div className="App-container">
<Switch>
<Route path="/login" component={Login} exact />
<Route path="/forgotpassword" component={ForgotPassword} exact />
<Route path={"/"} component={SubNav} />
</Switch>
<Route exact path={"/"} component={Overview} />
<Route path={"/overview"} component={() => <Overview />} />
</div>
</Router>
</div>
);
}
export default App;
For example, in my Login component, I have the following imports...
import React from 'react';
import './Login.scss';
import LoginBenefits from './LoginBenefits';
import LoginFormContainer from './LoginFormContainer';
The issue I am having here with the import of the Login.scss
In this file I do imports of specific other scss files that are related to the Login Component. Say, for example, I had one that styled a class called .Tabs
#import "../../scss/_variables";
$Tabs-padding: 15px;
#import "../tabs/Tabs.scss";
.Login {....
Now for example, if in the ForgotPassword Component, if I were to add a div with a className of Tabs it would then style it correctly. This isn't what I want, it means that whatever is imported in the Login component gets loaded throughout the whole project, which means I cannot override any SASS variables without having to import the same SASS file again and makes the webpack bundled css file larger than it needs to be.
I guess my question is, how do I contain the Login.scss to only import when the Login component actually renders?
Or am I going about the whole imports in the wrong way?
What you have to understand is, when you import your scss files. They get converted to css and are rendered as 'internal styles' in the app. Basically they become global css rendered in the header. So unless you use scss properly and structure your css with a hierarchy you cannot achieve containment!
But what you have stumbled upon is an intriguing idea, which has
pushed the community to come up with a solution called css in js!
Look at this video!
The basic idea is to bring css into the React Component containing the styles inside the component. It is achieved using using template strings. This is groundbreaking because you now how the full power of javascript behind you to manipulate css!
This is an exhaustive list of frameworks that can help you with this. styled-components is the most widely adopted framework. But you can take a pick!
This is an example of how your code will look
import React from 'react';
import { render } from 'react-dom';
import styled from 'styled-components';
const Container = styled.div`
text-align: center;
`;
const Button = styled.button`
background-color: #ff0000;
width: 320px;
padding: 20px;
border-radius: 5px;
border: none;
outline: none;
&:hover {
color: #fff;
}
&:active {
position: relative;
top: 2px;
}
#media (max-width: 480px) {
width: 160px;
}
`;
const App = () => (
<Container>
<Button>Click me!</Button>
</Container>
);
render(<App />, document.getElementById('content'));
And styled components takes care of containing your css to the relevant component!
You need to bundle the all your scss file into single file. You can do this in webpack config file with use of ExtractTextPlugin
module: {
rules: [{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
}),
},
{
test: /js$/,
exclude: /(node_modules)/,
loader: "babel-loader",
}
]
},
plugins: [
new ExtractTextPlugin({
filename: "dist/assets/css/style.bundle.css"
})
]

Categories