Storybook cannot read property 'displayName' of undefined - reactjs

I have created a new component Navbar.jsx
import { Disclosure } from '#headlessui/react'
import Image from 'next/image'
import tacoPicture from '../public/lets-taco-bout-it.png'
function classNames(...classes) {
return classes.filter(Boolean).join(' ')
}
export const Header = () => {
return (
<Disclosure as="nav" className="bg-white shadow">
{({ open }) => (
<>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-16">
<div className="flex items-center">
<div className="flex-shrink-0">
<Image src={tacoPicture} alt="Picture of the author" />
</div>
</div>
</div>
</div>
</>
)}
</Disclosure>
)
}
So, this needs to be described as a story. In my file Navbar.stories.jsx I do the following
import { Navbar } from './Navbar';
export default {
title: 'Example/Navbar',
component: Navbar,
};
const Template = (args) => <Navbar {...args} />;
export const Default = Template.bind({});
And get the error:
I am new to storybook, however it seems to be a react issue, which I am also new to.

Faced the same issue. What is the mistake I have done is using the wrong import.
So i change this,
import { Button } from './button';
Into this
import Button from './button';
I got the idea from #Katharina's answer. thanks...

Apparently, I was importing a Navbar, my component's name is Header. Also there is a difference between export default function () {} and export const x = () => {}, which is crucial for importing.

I was getting the same error. In my case, the problem wasn't in imports but in using styled-components' css attribute (using babel-plugin-styled-components).
<Button
variant={"color"}
// this caused it
css={`
margin-right: 24px;
`}
>
The workaround was to get rid of the css attribute by replacing the Button component with a new styled one. Like this:
const SubmitButton = styled(Button)`
margin-right: 24px;
`;

I got this error, I was working on an existing react library and making/editing things by hand. The solution was to find the index.ts in the src folder and add my new components to it manually.
Hope this helps someone

If you want to import your component using this syntax:
import { Button } from './button';
You can use named export from your button component
export { Button }
otherwise you have to import it without the curly braces like so:
import Button from './button';
you can read more about named vs default exports here:
https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export
also this article has a nice explanation:
https://medium.com/#timoxley/named-exports-as-the-default-export-api-670b1b554f65

Related

How to pass CSS class names in React JS

I want to change the width of a component whenever I click a button from another component
This is the button in BiCarret:
import { useState } from "react";
import { BiCaretLeft } from "react-icons/bi";
const SideBar = () => {
const [open, setOpen] = useState(true);
return (
<div className="relative">
<BiCaretLeft
className={`${
open ? "w-72" : "w-20"
} bg-red-400 absolute cursor-pointer -right-3 top-5 border rounded-full`}
color="#fff"
size={25}
onClick={setOpen(!true)}
/>
</div>
);
};
export default SideBar;
and this is the component I want to change the width on click
import "./App.css";
import SideBar from "./components/SideBar/SideBar";
function App() {
return (
<div className="app flex">
<aside className="h-screen bg-slate-700"> // change the width here
<SideBar />
</aside>
<main className="flex-1 h-screen"></main>
</div>
);
}
export default App;
You have two simple solutions, either:
Create context
Crete context and store Open value in it, change it on click and in App react to it.
Dom manipulation
In app add ID to element you would like to change and onClick in the other component use document.getElementById(THE_ID).classList.add("new-class-for-increased-width") which gets the DOM element and adds class to it.

Issues with Next.js/React forwardRef() function

While developing a website for a class (I used a youtube tutorial to build the site), I am having this error show up in the console:
Although the site renders locally, this causes issues when I try to deploy it, as you can imagine. So I found the documentation for the React.forwardRef() and I implemented it like this in my code:
import React from 'react';
import Image from "next/image";
import styles from "../styles/PizzaCard.module.css";
import Link from 'next/link';
const PizzaCard = React.forwardRef(({pizza}, ref) => {
return <input ref={ref}/>>(
<div className={styles.container}>
<Link href={`/product/${pizza._id}`} passHref>
<Image src={pizza.img} alt="" width="500" height="500"/>
</Link>
<h1 className={styles.title}>{pizza.title}</h1>
<span className={styles.price}>${pizza.prices[0]}</span>
<p className={styles.desc}>
{pizza.desc}
</p>
</div>
);
});
export default PizzaCard;
And this in my PizzaList file:
import React from "react";
import styles from "../styles/PizzaList.module.css";
import PizzaCard from "./PizzaCard";
const PizzaList = React.forwardRef(({pizzaList}, ref) => {
return <input ref={ref}/>> (
<div className = {styles.container}>
<h1 className={styles.title}>The Mellowist Pizza in Town!</h1>
<p className={styles.desc}>
Mellow Yellow Pizzaria is a local Family Owned business providing
the community with tasty pizza made with Heart and Soul!
</p>
<div className={styles.wrapper}>
{pizzaList.map((pizza) => (
<PizzaCard key={pizza._id} pizza={pizza} />
))}
</div>
</div>
)
})
export default PizzaList
And here is where PizzaList is called:
import axios from "axios";
import Head from "next/head";
import Image from "next/image";
import { useState } from "react";
import Add from "../components/Add";
import AddButton from "../components/AddButton";
import Featured from "../components/Featured";
import PizzaList from "../components/PizzaList";
import styles from "../styles/Home.module.css";
export default function Home({pizzaList, admin}) {
const [close, setClose] = useState(true)
return (
<div className={styles.container}>
<Head>
<title>Mellow Yellow Pizzaria</title>
<meta name="description" content="Created by Yellow project team at CTU" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Featured/>
{admin && <AddButton setClose={setClose}/>}
<PizzaList pizzaList={pizzaList} />
{!close && <Add setClose={setClose}/>}
</div>
)
}
export const getServerSideProps = async (ctx) =>{
const myCookie = ctx.req?.cookies || ""
let admin = false
if(myCookie.token === process.env.TOKEN){
admin = true
}
const res = await axios.get("http://localhost:3000/api/products")
return{
props:{
pizzaList:res.data,
admin,
}
}
}
Although this made the console errors go away, now my pizza products do not display, as you can see:
So, what am I doing wrong? If you need me to post more of my code, please let me know and I will, I'm not sure what all you'd need to see.
EDIT:
Here is my original code before adding the forwardRef()...this is the code that gives me the console errors in the first screenshot, I added the forwardRef() to PizzaCard and PizzaList because those are 2 spots that the console suggested I check (the list of "at ..." in the console window)
PizzaCard:
import React from 'react';
import Image from "next/image";
import styles from "../styles/PizzaCard.module.css";
import Link from 'next/link';
const PizzaCard = ({pizza}) => {
return (
<div className={styles.container}>
<Link href={`/product/${pizza._id}`} passHref>
<Image src={pizza.img} alt="" width="500" height="500"/>
</Link>
<h1 className={styles.title}>{pizza.title}</h1>
<span className={styles.price}>${pizza.prices[0]}</span>
<p className={styles.desc}>
{pizza.desc}
</p>
</div>
);
};
export default PizzaCard;
PizzaList:
import styles from "../styles/PizzaList.module.css";
import PizzaCard from "./PizzaCard";
const PizzaList = ({pizzaList}) => {
return (
<div className = {styles.container}>
<h1 className={styles.title}>The Mellowist Pizza in Town!</h1>
<p className={styles.desc}>
Mellow Yellow Pizzaria is a local Family Owned business providing
the community with tasty pizza made with Heart and Soul!
</p>
<div className={styles.wrapper}>
{pizzaList.map((pizza) => (
<PizzaCard key={pizza._id} pizza={pizza} />
))}
</div>
</div>
)
}
export default PizzaList
Here is a link to my github with all of the code:
https://github.com/InvisibleH3R0/mellowyellowpizzaria
Original Issue Fixed
So the fix for the ref issue was to wrap the image (in the first set of code I posted) in <a></a>
But now...when I load the site (locally) the homepage starts off just white, if I refresh the page it comes up...but when I inspect the page when first loading, it shows a internal server (500) error:
This leads me to believe the issue lies in the api/products or api/options code, that is where the GET methods are

React import error when using export default

I have a
menu-item.component in src/components/menu-item/menu-item.component.jsx
directory.component in src/components/directory/directory.component.jsx.
In menu-item.component:
import React from "react";
import withRouter from "react-router-dom";
import "./menu-item.styles.scss";
export const MenuItem = ({ title, imageUrl, size }) => (
<div className={`${size} menu-item`}>
<div
className="background-image"
style={{
backgroundImage: `url(${imageUrl})`
}}
/>
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">Alışverişe Başla</span>
</div>
</div>
);
// export default MenuItem;
with this, the import statement import { MenuItem } from "../menu-item/menu-item.component"; in directory.component.jsx works well. When I remove export from function definition and instead add export default MenuItem; at the bottom, the npm start fails with:
Failed to compile.
./src/components/directory/directory.component.jsx
Attempted import error: 'MenuItem' is not exported from '../menu-item/menu-item.component'.
I'm new to react and following the exact code from a tutorial and it works well in the videos. Why this fails?
Try removing the brackets
import MenuItem from "../menu-item/menu-item.component"
When you do an 'export default', you dont need to be specific about the name when importing to get the default import (you can import it as Item or MenuI, for example, but always starting with a capital, to let React knows it's still a component);
Also, remove the export before the const declaration you're using export default

How to correctly use page components without GraphQL

I have a new Gatsby site, which has 3 pages (with more to come). I am finding that I am having to repeat lots of styling and I know there must be a correct way to avoid doing this but I'm unsure what. I'm using Emotion with Tailwind.
There is a hero element on all pages, which include a heading and description:
<Hero>
<Title>
Page title here
</Title>
<Lead>
Descirption text here
</Lead>
</Hero>
This is the styling for it:
const Hero = styled.header`
${tw`bg-blue-dark p-6`};
`
const Title = styled.h1`
${tw`text-white tracking-wide font-medium`};
`
const Lead = styled.p`
${tw`text-gray leading-relaxed mb-1`};
a {
${tw`text-white font-medium no-underline text-purple hover:text-white`};
}
`
Some pages also have action buttons:
<Actions>
<LinkPrimary to="/some-page/">Click for more</LinkPrimary>
<LinkSecondary to="/some-other-page/">Or click here</LinkSecondary>
</Actions>
Full page template looks like (this is what I'm duplicating for every new page):
import React from "react"
import Layout from "../components/layout"
import styled from "#emotion/styled"
import { Link } from "gatsby"
import tw from "tailwind.macro"
const Hero = styled.header`
${tw`bg-blue-dark p-6`};
`
const Title = styled.h1`
${tw`text-white tracking-wide font-medium`};
`
const Lead = styled.p`
${tw`text-gray leading-relaxed mb-1`};
a {
${tw`text-white font-medium no-underline text-purple hover:text-white`};
}
`
const Actions = styled.section`
${tw`text-center m-2 mt-8 mb-24`};
`
const LinkPrimary = styled(Link)`
${tw`block bg-pink hover:bg-green-light text-blue-dark font-bold no-underline py-4 px-4 m-4 rounded`}
`
const LinkSecondary = styled(Link)`
${tw`block bg-regal-blue hover:bg-blue-light text-pink hover:text-white font-semibold no-underline py-4 px-4 m-4 rounded`}
`
export default () => (
<Layout>
<Hero>
<Title>
Hey I'm The About Page
</Title>
<Lead>
Learn all about us
</Lead>
</Hero>
<Actions>
<LinkPrimary to="/some-page/">Click for more</LinkPrimary>
<LinkSecondary to="/some-other-page/">Or click here</LinkSecondary>
</Actions>
</Layout>
)
The problem I have is for every new page I have to repeat the styling. I am manually creating these pages within src/pages and editing the title and description for each page. Pages that have the buttons I am also editing the button text and URL.
I'm guessing there must be a way to create a "hero" component which includes the title and lead with their styling, then import it into each page and edit the content on a per-page basis.
Not all pages will have the action buttons so they probably need to be in their own component and just imported where needed.
If someone could give me a basic demo or link to some docs where this is explained that would be much appreciated. All my research only gives examples of how to do this querying with GraphQL.
Alright, I think I have something that works so will post an answer.
Create a Hero component src/components/hero.js
import React from "react"
import styled from "#emotion/styled"
import tw from "tailwind.macro"
const Header = styled.header`
${tw`p-6`};
`
const Title = styled.h1`
${tw`text-white tracking-wide text-lg font-medium`};
`
const Lead = styled.p`
${tw`text-purple-light leading-relaxed text-lg`};
`
const Hero = props => (
<Header>
<Title>{props.heading}</Title>
<Lead>{props.text}</Lead>
</Header>
)
export default Hero
Then use it in your pages, index page, about page, wherever it's needed:
import React from "react"
import Layout from "../components/layout"
import Hero from "../components/hero"
export default () => (
<Layout>
<Hero
heading="Hello world!"
text="This is the lead text for this page."
/>
...
</Layout>
)
The great thing about this is now my styling for my hero element is all contained in my Hero component. I will probably do the same for the call to action buttons.
If you want to have links or html tags in your text, you can do the following:
<Hero
heading={[<em>Links</em>, " that", <br />, " go places"]}
text={[
"You can write some text here followed by ",
<Link to="/learn/">
a link to another page
</Link>,
" that you can click.",
]}
/>

React-reveal Image Slide

I am using react reveal and doing an image slide up transition but the image is not showing, I have given the code below as well as the output image. I have added a picture which shows whats happening. the link in the picture was supposed to be an image but it's showing just Link
import React from 'react';
import { Link } from 'react-router-dom';
import Reveal from 'react-reveal';
import 'animate.css/animate.css';
const generateBlocks = ({blocks}) =>{
if(blocks){
return blocks.map((item)=>{
const styles = {
background:`url('/images/blocks/${item.image}') no-repeat `
}
return(
<Reveal key={item.id} effect="animated fadeInUp"
className={`item ${item.type}`}>
<div className="veil"></div>
<div
className="image"
style={styles} >
</div>
<div className="title">
<Link to={item.link}>{item.title}</Link>
</div>
</Reveal>
)
})
}
}
const Blocks = (props) =>{
return(
<div className ="home_blocks">
{generateBlocks(props)}
</div>
)
}
export default Blocks;][1]
Heve you tried to import the right component from Reveal:
import Reveal from 'react-reveal/Reveal';
Have a look into the Documentation: https://www.react-reveal.com/examples/common/custom/

Resources