ReferenceError: Helmet is not defined in Fusion.js - reactjs

I was building a Todo app referring to Fusion.js docs
I added fusion-plugin-react-helmet-async plugin using yarn but it seem to have an error.
I tried to import Helmet but that does not seem to work. Is there something that I'm missing. Could anyone please help?
Code
import React, { useState } from "react";
const Root = () => {
const [todos, setTodos] = useState([]);
const [inputText, setInputText] = useState("");
...
return (
<React.Fragment>
<Helmet>
<style>
{`
body {
background-color: #f5f5f5;
font: 24px 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
`}
</style>
</Helmet>
<h1>todos</h1>
<div className="container">
...
</div>
</React.Fragment>
);
};
export default <Root />;
Error Message

import statement was missing in the docs. I opened a GitHub issue on this and someone from the Fusion.js team corrected the docs.
After adding the below statement, it worked.
import { Helmet } from "fusion-plugin-react-helmet-async";

Related

I want to know how to send props through Link

I made two components and I want to send a props after connecting these components by Link. I'm working on it without using redux, but I found a way to send props and made a code, but the value doesn't come out because I think the method is wrong. I'd appreciate it if you let me know thanks.
SingUp.jsx:
This is the component I'm trying to send a prop. I checked that the value comes out well if I put the value in the input tag. So I think you just need to check the link tag part! I only sent the email value and put email in props to check it
import React, { useState } from 'react'
import { Link } from 'react-router-dom';
import styled from 'styled-components';
import SignUpEmailInput from '../components/SingUp/SignUpEmailInput';
import SignUpLoginButton from '../components/SingUp/SignUpLoginButton';
import SignUpNameInpu from '../components/SingUp/SignUpNameInpu';
import SignUpPassInput from '../components/SingUp/SignUpPassInput';
import SignUpUserInput from '../components/SingUp/SignUpUserInput';
const SignUpWrap = styled.div`
flex-direction: column;
display: flex;
position: relative;
z-index: 0;
margin-bottom: calc(-100vh + 0px);
color: rgb(38,38,38);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 18px;
`
function SignUp() {
const [email, setEmail] = useState("");
const [name, setName] = useState("");
const [userName, setUserName] = useState("");
const [passWord, setPassWord] = useState("");
return (
<SignUpWrap>
<div>
<SignUpEmailInput email={email} setEmail={setEmail}/>
</div>
<div>
<SignUpNameInpu name={name} setName={setName}/>
</div>
<div>
<SignUpUserInput userName={userName} setUserName={setUserName} />
</div>
<div>
<SignUpPassInput passWord={passWord} setPassWord={setPassWord}/>
</div>
<div >
{/* I used Link here */}
<Link to={{pathname:'/birthday', state:{email:email}}} style={{textDecoration : 'none' ,color: 'inherit'}}>
<div>
<SignUpLoginButton email={email} name={name} userName={userName} passWord={passWord}/>
</div>
</Link>
</div>
</SignUpWrap>
)
}
export default SignUp;
Birthday.jsx:
This is the component that I want to receive a prop. I checked that the two components are moved through Link. Can I also know how to get a props value here? I want to check if it went well through console.log
import React, { useState } from 'react'
function Birthday({email, name, userName, passWord}) {
console.log(location.state.email)
return (
<>
Hi
</>
)
}
export default Birthday;
you can use state prop as below - using RR V6 version FYI
<Link to="/hello" state={{ data: 'dummy' }}>
and use useLocation hook to collect data in respective component as
const location = useLocation();
console.log(location.state);
A sample e.g. below
https://stackblitz.com/edit/react-ts-mxqsgj?embed=1&file=App.tsx
<Link to="/birthday" state={{email : email }} style={{textDecoration : 'none' ,color: 'inherit'}}>
you can get by using useLocation
import React, { useState } from 'react';
import { useLocation } from 'react-router-dom'
function Birthday() {
const location = useLocation()
const { email } = location.state
console.log(email)
return email
}
export default Birthday;

Scroll to a component when a button is clicked in React JSX

I've looked at way too many ways to scroll to a certain component when clicking a button, but it's always in a JS file. Can't seem to get it to work in my JSX files project.
I've tried several libraries and methods such as "scrollTo", "scrollIntoView", "scrollToComponent"..
They pretty much all try to reference a component, but I can't seem to get it to work.
In JS it usually works when they use the "useRef" from react but, again, can't seem to do it in JSX.
Does anyone have any idea why and how to do it?
Something like:
const MyComponent = () => {
const scrollSomewhere = () => {
// PSEUDO-CODE - something along these lines maybe?
// scrollToComponent("Somewhere");
}
return (
<>
<MyCustomButton onClick={scrollSomewhere}> Click me! </MyCustomButton >
(...)
<MyCustomComponent ref="Somewhere"> I'm somewhere </MyCustomComponent>
</>
}
The ref needs to hold a reference the DOM element to which you want to scroll. Here's an example:
.container {
font-family: sans-serif;
}
.target {
background-color: black;
color: white;
margin: 100rem 0;
padding: 1rem;
}
<script src="https://unpkg.com/react#17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#17.0.2/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/#babel/standalone#7.16.3/babel.min.js"></script>
<div id="root"></div>
<script type="text/babel" data-type="module" data-presets="react">
const {useRef, useState} = React;
function Example () {
const elementRef = useRef(null);
const handleClick = () => {
if (elementRef.current) {
elementRef.current.scrollIntoView();
}
};
return (
<div className="container">
<div>The element you want to scroll to is below 👇</div>
<button onClick={handleClick}>Scroll to element</button>
<div className="target" ref={elementRef}>Here I am!</div>
</div>
);
}
ReactDOM.render(<Example />, document.getElementById('root'));
</script>

Alternative to createGlobalStyle from styled-components that can also be importable

we are currently loading Fonts and few other global styles like this:
import { createGlobalStyle } from 'styled-components';
export default createGlobalStyle`
#font-face {
font-family: 'Name';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/name/v12/iJWZBXyIfDnIV5PNhY1KTN7Z-Yh-B4iFU0U1Z4Y.woff2) format('woff2');
}
// more fonts..
}
And in every _app.tsx (from every project in repo) we just
import GlobalStyle from #our-company/ui;
// few other imports
const AppProviders = ({ children, messages, locale }: Props): JSX.Element => {
return (
<IntlProvider
locale={locale || 'en-GB'}
key={locale}
messages={messages[locale]}
defaultLocale="en-GB"
>
<GlobalStyle />
<DsThemeProvider
locale={locale}
>
{children}
</DsThemeProvider>
</IntlProvider>
);
};
But we noticed unnecessary font reloads caused by this GlobalStyle when clicking, for example, in checkbox elements (tried putting this in a .css and just load it and never happens again).
Any idea how could export this styles as GlobalStyle name without using styled-components so we don't have to change all import from all apps in the project?
why you dont create main.css and import it on your index.css or app.css , its download and cache on users browser so you don't need to use global styled component anymore
It seems like you're looking for something like injectGlobal:
import { injectGlobal } from 'styled-components';
injectGlobal`
/* your #font-face stuff here */
`
This seems like it would be a good fit for your situation, as it would be relatively easy to transition from the existing structure using createGlobalStyle to one that uses this.
In your case, the code would look like:
import { injectGlobal } from 'styled-components';
injectGlobal`
#font-face {
font-family: 'Name';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/name/v12/iJWZBXyIfDnIV5PNhY1KTN7Z-Yh-B4iFU0U1Z4Y.woff2) format('woff2');
}
// more fonts..
}
If you wish to use a solution that is backwards-compatible with any code that is rendering <GlobalStyle />, you can include a null component as the default export as a stop-gap solution, alongside your injectGlobal code:
export default () => null;
Would this solve your problem?
You can also bind the style directly inside the JS file
var stylingObject = {
div: {
color: "red",
border: "1px solid red"
}, input: {
margin: "2px",
padding: "5px"
}
}
function App() {
return (
<div style={stylingObject.div}>
<input style={stylingObject.input} type="text" />
</div>
);
}
Originally I had hoped to import some CSS file with the fonts defined there and then just importing it so it would affect the entire page, obviously because the way react works such a thing isn't possible cause it would take place only in the imported component not in the one that did the import.
the reason createGlobalStyle from styled-components renders each time is also due to react's workings - when we set the style for a "component like" (or actual component) object, like every react component its not static and renders only when needed. Even if we make it render by force on page load its not the same one (cause on each page we render it separately) so keeping up with the current config doesn't seem to be possible by react's standard.
If we want to make the styles static or "more" static we would have to :
either import them in each page separately - making us do a major refactor
or use either createGlobalStyle (allowing us to use our already created styled-components component) or importing a main css file in the main application component like in the example below:
globalStyles.js
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
padding: 0;
background: teal;
font-family: Open-Sans, Helvetica, Sans-Serif;
}
`;
export default GlobalStyle;
App.js
import React, { Fragment } from 'react';
import GlobalStyle from './theme/globalStyle';
import Content from './components/Content';
function App() {
return (
<Fragment>
<GlobalStyle />
<Content />
</Fragment>
);
}
export default App;
If you have a rather large global stylesheet like we did while migrating, you can use styled-components css method to leverage styled-components (css) IDE syntax highlighting & linting you can also do the following:
import React from 'react'
import { createGlobalStyle, css } from 'styled-components'
const Reset = css`
* {
box-sizing: border-box;
}
`
const Accessibility = css`
.hidden {
display: none !important;
visibility: hidden;
}
`
const BaseStyles = createGlobalStyle`
${Reset};
${Accessibility};
`
export const GlobalStyles = () => (
<>
<BaseStyles />
</>
)
Import GlobalStyles and render as sibling to {children}

why styled component styling not adding

i was scratching my head from the last 2 hours that why this 3 rd party styled component is not adding i it .have a look
import React from 'react';
import styled from 'styled-components'
const StyleDiv =styled.div`
#media(max-width:600px){
body{
background-color: red;
}
}`
const Person= (props)=>{
return <StyleDiv>
<h1 onClick={props.click}>i am {props.name} and {props.age} years old as you know me as {props.children} </h1>
<input type="text" onChange={props.changed} />
</StyleDiv>
}
export default Person;
If you put selectors within the template string without the ampersand, they will refer to children of the component. https://styled-components.com/docs/basics#pseudoelements-pseudoselectors-and-nesting
Basically you can't select body within your div and you probably shouldn't.
you cannot apply global styles like this to a component, for applying global styles (i.e. styles to body, html etc.) styled-components gives a createGlobalStyles utility, it can be used like this:
import { createGlobalStyles } from 'styled-components';
const GlobalStyles = createGlobalStyle`
#media (max-width: 600px) {
body {
background-color: red;
}
}
`;
// Render GlobalStyles to the root lvvel of your app
ReactDOM.render(
<>
<GlobalStyles />
<App />
</>,
document.getElementById('root');
);
Hope it helps :)

Flash Of Unstyled Text (FOUT) on reload using next.js and styled components

I'm using global style from styled components with next.js and every time I reload my page I can see the font flickering.
I have my font files in public/fonts/Inconsolata
I've looked everywhere in spectrum chat, next.js github issues but can't seem to find any solution.
pages/index.js
import styled from 'styled-components';
const H1 = styled.h1`
font-family: 'Inconsolata Bold';
font-weight: 700;
color: #000;
`;
const index = () => {
return (
<div>
<H1>font flashes</H1>
</div>
);
};
export default index;
pages/_app.js
import App from 'next/app';
import React from 'react';
import GlobalStyle from '../src/style/globalStyle';
export default class MyApp extends App {
render() {
const { Component, pageProps } = this.props;
return (
<>
<GlobalStyle />
<Component {...pageProps} />
</>
);
}
}
pages/_document.js
import Document from 'next/document';
import { ServerStyleSheet } from 'styled-components';
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => sheet.collectStyles(<App {...props} />)
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
};
} finally {
sheet.seal();
}
}
}
style/globalStyle.js
import { createGlobalStyle } from 'styled-components';
const globalStyle = createGlobalStyle`
#font-face {
font-family: 'Inconsolata';
src: url('./fonts/Inconsolata/Inconsolata-Regular.woff2') format('woff2'),
url('./fonts/Inconsolata/Inconsolata-Regular.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: fallback;
}
#font-face {
font-family: 'Inconsolata Bold';
src: url('./fonts/Inconsolata/Inconsolata-Bold.woff2') format('woff2'),
url('./fonts/Inconsolata/Inconsolata-Bold.woff') format('woff');
font-weight: 700;
font-style: bold;
font-display: fallback;
}
`;
export default globalStyle;
UPDATE:
Next.js released a new feature called Automatic Webfont Optimization.
Just include your font (it works only with Google Fonts so far) and it will be included as raw css on build-time.
// Before
<link
href="https://fonts.googleapis.com/css2?family=Inter"
rel="stylesheet"
/>
// After
<style data-href="https://fonts.googleapis.com/css2?family=Inter">
#font-face{font-family:'Inter';font-style:normal.....
</style>
Check out how Next.js guys handle it on their website, which is open-source and can be found here. Check it out, it worked for me.
Import your used font in css #font-face via preload link
<link
rel="preload"
href="/assets/my-font.woff2"
as="font"
type="font/woff2"
/>
Your font declaration should be on SSR HTML page, so use <style jsx global /> to include it in your page. It can be an external file or right directly in style element.
I had a similar problem with NextJS 12, Google Fonts and SCSS modules.
My partial solution was to
'preload' the resources being requested in any #font-face rules in any CSS file - load the fonts more eagerly
set font-display: optional - tell CSS to use fallback if font not loaded in time
This means no Flash Of Unstyled Text (FOUT) but on slower connections a fallback font will be used on first load instead.
<head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preload"
href="https://fonts.gstatic.com/s/inconsolata/v21/QlddNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLyya15IDhunA.woff2"
as="font"
type="font/woff2"
crossOrigin=""
/>
<link
rel="preload"
href="https://fonts.gstatic.com/s/inconsolata/v21/QlddNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLyx615IDhunJ_o.woff2"
as="font"
type="font/woff2"
crossOrigin=""
/>
// CSS file with #font-face rules and font-display: optional
<link
href="https://fonts.googleapis.com/css2?family=Inconsolata:wght#300;400;700&display=optional"
rel="stylesheet"
/>
</head>
In this example, the last link element requests a CSS file which has a number of #font-face rules with src declarations and url() values.
If the resources in the url() functions aren't preloaded in the head then they wont be requested until the CSS is parsed.
I think this is what causes the FOUT.
By including <link rel="preload" src="..."/> elements fonts can be loaded sooner.
And setting font-display: optional tells the browser that if the font hasn't loaded in time to use a fallback.
The site I was working on: Soundboard
Create an style.css file in your public/fonts/ directory. Copy and paste your #font-face part in style.css.
style.css
#font-face {
font-family: "Inconsolata";
src: url("./fonts/Inconsolata/Inconsolata-Regular.woff2") format("woff2"),
url("./fonts/Inconsolata/Inconsolata-Regular.woff") format("woff");
font-weight: 400;
font-style: normal;
font-display: fallback;
}
#font-face {
font-family: "Inconsolata Bold";
src: url("./fonts/Inconsolata/Inconsolata-Bold.woff2") format("woff2"),
url("./fonts/Inconsolata/Inconsolata-Bold.woff") format("woff");
font-weight: 700;
font-style: bold;
font-display: fallback;
}
In your pages/_app.js import the style.css file in head.
_app.js
import App from 'next/app';
import React from 'react';
import Head from "next/head";
import GlobalStyle from '../src/style/globalStyle';
export default class MyApp extends App {
render() {
const { Component, pageProps } = this.props;
return (
<>
<GlobalStyle />
<Head>
<link rel="stylesheet" href="/fonts/style.css" />
</Head>
<Component {...pageProps} />
</>
);
}
}
Hat tip to Raul Sanchez on dev.to for the answer to this one:
Next doesn't fetch styled-components styles on the server, to do that you need to add this page to pages/_document.js:
import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
}
} finally {
sheet.seal()
}
}
}
This code may update, so check Next's styled-components example for the latest.
I had the same problem and after hours of experimenting with different methods npm package fontfaceobserver solved the problem for me.
With the package you can tell your app to render only after fonts are loaded, thus avoiding FOUT like so:
import FontFaceObserver from "fontfaceobserver";
const font = new FontFaceObserver("Inconsolata");
font.load().then(()=> {
ReactDOM.render(<App />,document.getElementById("root"));
}

Resources