React-use-gesture not working with Storybook - reactjs

I have my component and the storybook stories file, it renders with no errors but it is not draggable. I am basing my studies into this example from the react-use-gesture Github. I noticed that if I start a new project with create-react-app and paste this code there it works fine, but using storybook it doesn't work. I also notice that in my code the element looks like <div style="x: 0px; y: 0px;"></div> instead of <div style="transform: none;"></div> (code from the example that works), I've been researching and I couldn't find a solution so I came to ask the help of this awesome community.
Goal: To have a draggable card component story on react storybook, using react-spring and react-use-gesture.
Expected results: To be able to drag the component around.
Actual results: Component is not draggable
Error Messages: none.
Component's code:
import React from 'react'
import { useSpring, animated } from 'react-spring'
import { useDrag } from 'react-use-gesture'
export function Card() {
const [props,
set] = useSpring(() => ({ x: 0, y: 0, scale: 1 }))
const bind = useDrag(({ down, movement: [x, y] }) => {
set({ x: down ? x : 0, y: down ? y : 0, scale: down ? 1.2 : 1 })
})
return <animated.div {...bind()} style={props} />
}
export default Card;
Stories code:
import React from 'react'
import { storiesOf } from '#storybook/react'
import Card from './Card'
import './card.css'
const Body = ({ children }: any) => (
<div className="wrapper">
<style
dangerouslySetInnerHTML={{ __html: `body { margin: 0; }` }}
/>
{children}
</div>
)
storiesOf('UI Components | Card', module)
.add("Simple Card", () => (
<Body>
<Card />
</Body>
))
You can check my github repo for this and run npm install and npm run storybook
Here is the folder that contains the code above ^ if you want to check the code only.

I found the solution, the codesandbox is using the latest beta of useSpring.
The versions I had were:
"react-spring": "^8.0.27",
"react-use-gesture": "^6.0.14",
and the solution
"react-spring": "9.0.0-beta.34",
"react-use-gesture": "latest"
Maybe this will be of help for someone else as well.

Related

Issue using eventHandlers with react-leaflet and next.js

I'm trying to use eventHandlers with react-leaflet in a next.js application, but the events are never being fired.
Here is an example of the code I'm using in my Map component:
import { MapContainer, Rectangle } from "react-leaflet";
const Map = () => {
return (
<MapContainer center={[25, 25]} zoom={1} style={{ height: 600, width: 600 }}>
<Rectangle
bounds={[
[0, 0],
[50, 50],
]}
eventHandlers={{
click: () => console.log("clicked.."),
}}
/>
</MapContainer>
);
};
export default Map;
I've tried using this code outside of a next.js application (plane react app) and it worked as expected, but when I use it in a next.js application, the event is never fired.
Here is an example of how I'm rendering the Map component in my index.js file:
import dynamic from "next/dynamic";
const Map = dynamic(() => import("../components/Map"), {
ssr: false,
});
export default function Home() {
return (
<>
<Map />
</>
);
}
I also tried using this code in a codesandbox, but I couldn't get the sandbox to work (it crashed). Also tested it on the live editor on https://react-leaflet.js.org/docs/example-popup-marker/ and replacing the marker with the rectangle component, the event is triggered on click.
Has anyone else experienced this issue and found a solution?
Thanks in advance for any help!

Swiper Component not working in React and throwing Erros

So I am following along with a course by Traversy Media called "React Front To Back 2022", at the 16th section of the course in the 5th and 6th videos, he was using the Swiper component. I was following along step-by-step but at the end, it threw an error, so after a bit of thinking and googling I decided to see the solution of the GitHub repository posted by him of the project, I compared the code, seemed the same, I copied it, still, it threw the errors and didn't render the page.
I couldn't find a fix anywhere(google, documentation, youtube, etc), so hopefully someone can help me here. Thank you in advance for the help.
The Errors:
init-swiper.js:25 Uncaught TypeError: Cannot read properties of undefined (reading 'pagination')
at mountSwiper (init-swiper.js:25:1)
at swiper.js:136:1
at commitHookEffectListMount (react-dom.development.js:23049:1)
at invokeLayoutEffectMountInDEV (react-dom.development.js:25010:1)
at invokeEffectsInDev (react-dom.development.js:27304:1)
at commitDoubleInvokeEffectsInDEV (react-dom.development.js:27280:1)
at flushPassiveEffectsImpl (react-dom.development.js:27007:1)
at flushPassiveEffects (react-dom.development.js:26935:1)
at performSyncWorkOnRoot (react-dom.development.js:26032:1)
at flushSyncCallbacks (react-dom.development.js:12009:1)
react_devtools_backend.js:4026 The above error occurred in the <Swiper> component:
at http://localhost:3000/static/js/bundle.js:131862:66
at Slider (http://localhost:3000/static/js/bundle.js:1549:66)
at main
at div
at Explore
at Routes (http://localhost:3000/static/js/bundle.js:120121:24)
at Router (http://localhost:3000/static/js/bundle.js:120046:30)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:118774:23)
at App
Uncaught TypeError: Cannot read properties of undefined (reading 'pagination')
at mountSwiper (init-swiper.js:25:1)
at swiper.js:136:1
at commitHookEffectListMount (react-dom.development.js:23049:1)
at invokeLayoutEffectMountInDEV (react-dom.development.js:25010:1)
at invokeEffectsInDev (react-dom.development.js:27304:1)
at commitDoubleInvokeEffectsInDEV (react-dom.development.js:27280:1)
at flushPassiveEffectsImpl (react-dom.development.js:27007:1)
at flushPassiveEffects (react-dom.development.js:26935:1)
at performSyncWorkOnRoot (react-dom.development.js:26032:1)
at flushSyncCallbacks (react-dom.development.js:12009:1)
The Code:
import { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { collection, getDocs, query, orderBy, limit } from 'firebase/firestore'
import { db } from '../firebase.config'
import SwiperCore, { Navigation, Pagination, Scrollbar, A11y } from 'swiper'
import { Swiper, SwiperSlide } from 'swiper/react'
import 'swiper/swiper-bundle.css'
import Spinner from './Spinner'
SwiperCore.use([Navigation, Pagination, Scrollbar, A11y])
function Slider() {
const [loading, setLoading] = useState(true)
const [listings, setListings] = useState(null)
const navigate = useNavigate()
useEffect(() => {
const fetchListings = async () => {
const listingsRef = collection(db, 'listings')
const q = query(listingsRef, orderBy('timestamp', 'desc'), limit(5))
const querySnap = await getDocs(q)
let listings = []
querySnap.forEach((doc) => {
return listings.push({
id: doc.id,
data: doc.data(),
})
})
setListings(listings)
setLoading(false)
}
fetchListings()
}, [])
if (loading) {
return <Spinner />
}
if (listings.length === 0) {
return <></>
}
return (
listings && (
<>
<p className='exploreHeading'>Recommended</p>
<Swiper slidesPerView={1} pagination={{ clickable: true }}>
{listings.map(({ data, id }) => (
<SwiperSlide
key={id}
onClick={() => navigate(`/category/${data.type}/${id}`)}
>
<div
style={{
background: `url(${data.imgUrls[0]}) center no-repeat`,
backgroundSize: 'cover',
}}
className='swiperSlideDiv'
>
<p className='swiperSlideText'>{data.name}</p>
<p className='swiperSlidePrice'>
${data.discountedPrice ?? data.regularPrice}{' '}
{data.type === 'rent' && '/ month'}
</p>
</div>
</SwiperSlide>
))}
</Swiper>
</>
)
)
}
export default Slider
GitHub link to the repo
I'm currently facing same issue while following the course On udemy can't seem to find any difference in my code. The fix was, I updated Swiper to the latest version using npm i swiper#latest then changed my imports to import {Navigation, Pagination, Scrollbar, A11y } from 'swiper'
import { Swiper, SwiperSlide } from 'swiper/react'
import 'swiper/css'
and finally updated my swiper components to <Swiper
slidesPerView={1}
pagination={{ clickable: true }}
modules={[Navigation, Pagination, Scrollbar, A11y]}
navigation
scrollbar={{ draggable: true }}
>
{listing.imgUrls.map((url, index) => (
<SwiperSlide key={index}>
<div
style={{
background: `url(${listing.imgUrls[index]}) center no-repeat`,
backgroundSize: 'cover',
minHeight: '26rem',
}}
className='swiperSlideDiv'
></div>
</SwiperSlide>
))}
</Swiper>
Try switching versions for switcher package.
Checkout the package.json of traversary's repo: https://github.com/bradtraversy/house-marketplace/blob/main/package.json
Its coming due to <react.strictmode> remove it from index.js and it works but I don't know why strict mode causes this error

How to use gatsby background image plugin

I'm new to gatsby and i'm trying to use gatsby background image plugin but it does not work, the image wont show on screen.
Here's my code :
import * as React from "react"
import { graphql, useStaticQuery } from 'gatsby'
import { createGlobalStyle } from "styled-components"
import BackgroundImage from 'gatsby-background-image'
const GlobalStyle = createGlobalStyle`
body{
background-color: #270A63;
margin : 0px;
display:flex;
}`
const Layout = (props, { children }) => {
const data = useStaticQuery(
graphql`
query {
bgImage : file(relativePath: {eq: "background.png"}) {
childImageSharp {
gatsbyImageData(quality: 90)
}
}
}
`
)
const imageData = data.bgImage.childImageSharp.gatsbyImageData;
return (
<React.Fragment>
<GlobalStyle />
<BackgroundImage
Tag="section"
image={imageData}
>
</BackgroundImage>
</React.Fragment>
)
}
export default Layout
Layout is a custom component that I'm using in index page.
I used console.log to check imageData and it is an object that looks like this :
{bgImage:
childImageSharp:
gatsbyImageData:
backgroundColor: "#680818"
height: 1117
images:
fallback: {src: '/static/32d467ee3060062ab794e34f2002c807/f89cf/background.png', srcSet: '/static/32d467ee3060062ab794e34f2002c807/5829e/bac…60062ab794e34f2002c807/f89cf/background.png 1010w', sizes: '(min-width: 1010px) 1010px, 100vw'}
sources: [{…}]
[[Prototype]]: Object
layout: "constrained"
width: 1010}
I don't understand why it does not work.
Thank you for your help !
As per your GraphQL, you are using a Gatsby version greater or equal than 3. I think your snippet should look like something like:
import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import { getImage, GatsbyImage } from "gatsby-plugin-image"
import { convertToBgImage } from "gbimage-bridge"
import BackgroundImage from 'gatsby-background-image'
const GbiBridged = () => {
const { bgImage }= useStaticQuery(
graphql`
query {
bgImage : file(relativePath: {eq: "background.png"}) {
childImageSharp {
gatsbyImageData(quality: 90)
}
}
}
`
)
const image = getImage(bgImage)
const backgroundImage= convertToBgImage(image)
return (
<React.Fragment>
<GlobalStyle />
<BackgroundImage
Tag="section"
{...backgroundImage}
preserveStackingContext
>
<div style={{minHeight: 1000, minWidth: 1000}}>
<GatsbyImage image={image} alt={"testimage"}/>
</div>
</BackgroundImage>
</React.Fragment>
)
}
export default GbiBridged
Modified from: https://www.gatsbyjs.com/plugins/gatsby-background-image/#gatsby-34--gatsby-plugin-image applying your code
Gatsby changed the image plugin from gatsby-image (Gatsby 1 and 2) to gatsby-plugin-image (version 3 onwards). Among other things, it has changed the internal GraphQL nodes of the image data, hence the workaround of using gatsby-background-image has also changed accordingly. In your case, you are using the deprecated version of gatsby-image so your code is not able to display the image.
You can follow the full discussion in this GitHub thread: https://github.com/timhagn/gatsby-background-image/issues/141
I'd recommend not using any external plugins for this but using CSS to achieve this. This way you don't have to learn any new third-party plugins and can use the knowledge you have about CSS. Here's an example from the docs: https://www.gatsbyjs.com/docs/how-to/images-and-media/using-gatsby-plugin-image/#background-images
import * as React from "react"
import { StaticImage } from "gatsby-plugin-image"
export function Hero() {
return (
<div style={{ display: "grid" }}>
{/* You can use a GatsbyImage component if the image is dynamic */}
<StaticImage
style={{
gridArea: "1/1",
// You can set a maximum height for the image, if you wish.
// maxHeight: 600,
}}
layout="fullWidth"
// You can optionally force an aspect ratio for the generated image
aspectRatio={3 / 1}
// This is a presentational image, so the alt should be an empty string
alt=""
// Assisi, Perúgia, Itália by Bernardo Ferrari, via Unsplash
src={
"https://images.unsplash.com/photo-1604975999044-188783d54fb3?w=2589"
}
formats={["auto", "webp", "avif"]}
/>
<div
style={{
// By using the same grid area for both, they are stacked on top of each other
gridArea: "1/1",
position: "relative",
// This centers the other elements inside the hero component
placeItems: "center",
display: "grid",
}}
>
{/* Any content here will be centered in the component */}
<h1>Hero text</h1>
</div>
</div>
)
}

NextJS huge icon on initial page load after build project

I have some problem with icons and style were used in NextJs. I use material-ui in my project, developed time everything is ok but when i build project, the icons first be large then it gets normal. I try used other icon sets but result isn't change. Is it a NextJs bug?.
Before :
After :
This seem to help me with MUI icons
Before:
<WebAssetOffIcon sx={{maxWidth: 60, maxHeight: 60 }} />
After:
<WebAssetOffIcon style={{ maxWidth: 60, maxHeight: 60 }} />
Somone mentioned:
"The cause is the fact that the icon is being rendered before the CSS is loaded."
You can use the width property to set the icon default size, so when the CSS completely loads, they change to the icon's size.
<Icon width="16" />
add below code to your app.js/ts file it should fix your problem
import { config } from '#fortawesome/fontawesome-svg-core' // 👈
import '#fortawesome/fontawesome-svg-core/styles.css' // 👈
config.autoAddCss = false // 👈
credit goes https://github.com/FortAwesome/react-fontawesome/issues/234
Please add this code to "_document.js"
_document.js
import Document, {Html, Head, NextScript, Main} from 'next/document'
import {ServerStyleSheet} from 'styled-components';
export default class MyDocument extends Document {
static getInitialProps({renderPage}) {
const sheet = new ServerStyleSheet();
const page = renderPage(App => props => sheet.collectStyles(<App {...props}/>));
const styleTags = sheet.getStyleElement();
return {...page, styleTags};
}
render() {
return (
<Html lang="en">
<Head/>
<body>
<Main />
<NextScript/>
</body>
</Html>
)
}
}
~ Storm In Talent

Cannot check expect(elm).not.toBeVisible() for semantic-ui react component

I'm trying to test a react component and use expect(elm).not.toBeVisible() without success.
Update 3
I have cut down the code into this simpler form:
// ./TestItem.js
import React from 'react'
import './TestItem.css'
export default ({ hide }) => {
return <div className={hide ? 'shouldHide' : ''}>Text</div>
}
// ./__tests__/TestItem.test.js
import React from 'react'
import { render } from 'react-testing-library'
import TestItem from '../TestItem'
import 'jest-dom/extend-expect'
import 'react-testing-library/cleanup-after-each'
test.only('TestItem should render correctly', async () => {
const { getByText, debug } = render(<TestItem hide={true} />)
const itemNode = getByText('Text')
debug()
expect(itemNode).not.toBeVisible()
})
// ./TestItem.css
.shouldHide {
display: none;
}
Test result:
TestItem should render correctly
expect(element).not.toBeVisible()
Received element is visible:
<div class="shouldHide" />
7 | const itemNode = getByText('Text')
8 | debug()
> 9 | expect(itemNode).not.toBeVisible()
| ^
10 | })
11 |
debug() log:
console.log node_modules/react-testing-library/dist/index.js:58
<body>
<div>
<div
class="shouldHide"
>
Text
</div>
</div>
</body>
Update 2:
Okay it's getting pretty weird because I got the test to pass on codesanbox but still find no luck on my local machine.
My original question:
I use React, semantic-ui-react and react-testing-library.
Here is the code:
// ComboItem.test.js
import React from 'react'
import ComboItem from '../ComboItem'
import { render } from 'react-testing-library'
import comboXoi from '../images/combo-xoi.jpg'
import 'path/to/semantic/semantic.min.css'
describe('ComboItem', () => {
test('should render', async () => {
const { getByText, debug } = render(
<ComboItem image={comboXoi} outOfStock={false} />
)
const outOfStockNotice = getByText('Out of stock')
debug()
expect(outOfStockNotice).not.toBeVisible()
})
})
// ComboItem.js
import React from 'react'
import { Card, Image } from 'semantic-ui-react'
export default ({ image, outOfStock = false }) => {
return (
<Card>
<Image
src={image}
dimmer={{
active: outOfStock,
inverted: true,
'data-testid': 'combo-item-dimmer',
content: (
<span style={{ marginTop: 'auto', color: 'black' }}>
Out of stock
</span>
),
}}
/>
</Card>
)
}
What i get is the result here:
ComboItem › should render
expect(element).not.toBeVisible()
Received element is visible:
<span style="margin-top: auto; color: black;" />
at Object.test (src/app/screens/App/screens/SaleEntries/screens/CreateSaleEntry/screens/StickyRiceComboSelect/__tests__/ComboItem.test.js:14:34)
at process._tickCallback (internal/process/next_tick.js:68:7)
I have tried to see the component render result on the browser and the node outOfStockNotice in the test code is actually hidden because its parent, which is a div with class dimmer has style display: none.
According to jest-dom doc (which is used by testing-react-library:
toBeVisible
An element is visible if all the following conditions are met:
it does not have its css property display set to none
it does not have its css property visibility set to either hidden or collapse
it does not have its css property opacity set to 0
its parent element is also visible (and so on up to the top of the DOM tree)
Please help. I really don't know what could go wrong here.
Update:
I include the result of debug() here:
console.log node_modules/react-testing-library/dist/index.js:58
<body>
<div>
<div
class="ui card"
>
<div
class="ui image"
>
<div
class="ui inverted dimmer"
data-testid="combo-item-dimmer"
>
<div
class="content"
>
<span
style="margin-top: auto; color: black;"
>
Out of stock
</span>
</div>
</div>
<img
src="combo-xoi.jpg"
/>
</div>
</div>
</div>
</body>
Here is the answer according to the author of react-testing-library himself:
Probably a JSDOM limitation (in codesandbox it runs in the real browser). Actually, the problem is that the css isn't actually loaded into the document in JSDOM. If it were, then that would work. If you can come up with a custom jest transform that could insert the css file into the document during tests, then you'd be set.
So this would work if you were using CSS-in-JS.
So basically the import './TestItem.css' part in the test will not works because JSDOM doesn't load it, therefore jest-dom could not understand the class shouldHide means display: none.
Update:
According to this Stack Overflow thread, you can insert css into jsdom:
import React from 'react'
import { render } from 'react-testing-library'
import TestItem from '../TestItem'
import fs from 'fs'
import path from 'path'
test.only('TestItem should render correctly', async () => {
const cssFile = fs.readFileSync(
path.resolve(__dirname, '../TestItem.css'),
'utf8'
)
const { container, getByText, debug } = render(<TestItem hide={true} />)
const style = document.createElement('style')
style.type = 'text/css'
style.innerHTML = cssFile
container.append(style)
const itemNode = getByText('Text')
debug()
expect(itemNode).not.toBeVisible()
})
And then the test should pass.

Resources