Gatsby error Cannot read property 'fixed' of null - reactjs

I want to show my Products in the Menu section of index page . I try to display content such as text and images from contentful API but I get this error:
TypeError: Cannot read property 'fixed' of null
src/components/HomePageComponents/Product.js:6
3 | import { styles } from "../../utils"
4 | import Img from "gatsby-image"
5 |
6 | export default function Product({ product }) {
7 | const { name, price, ingredients } = product
8 | const { fixed } = product.img
This is my Product.js
import React from "react"
import styled from "styled-components"
import { styles } from "../../utils"
import Img from "gatsby-image"
export default function Product({ product }) {
const { name, price, ingredients } = product
const { fixed } = product.img
return (
<ProductWrapper>
<Img fixed={fixed} className="img" />
<div className="text">
<div className="product-content">
<h3 className="name">{name}</h3>
<h3 className="price">{price}</h3>
</div>
<p className="info">{ingredients}</p>
</div>
</ProductWrapper>
)
}
const ProductWrapper = styled.div`
#media (min-width: 576px) {
display: grid;
grid-template-columns: auto 1fr;
grid-column-gap: 1rem;
}
.img {
border-radius: 0.5rem;
}
.product-content {
display: flex;
justify-content: space-between;
font-size: 1.4rem;
text-transform: uppercase;
}
.name {
color: ${styles.colors.mainYellow};
margin-top: 0.5rem;
}
.price {
color: ${styles.colors.mainYellow};
margin-top: 0.5rem;
}
.info {
margin-top: 0.5rem;
word-spacing: 0.2rem;
text-transform: lowercase;
}
`
this is my Menu.js
import React from "react"
import Product from "./Product"
import { StaticQuery, graphql } from "gatsby"
import { Section, Title } from "../../utils"
import styled from "styled-components"
// import { Link } from "gatsby"
export default function Menu() {
return (
<Section>
<Title title="Featured items" message="Little taste" />
<ProductList>
<StaticQuery
query={graphql`
{
items: allContentfulMenu {
edges {
node {
name
price
id
ingredients
img {
fixed(width: 150, height: 150) {
...GatsbyContentfulFixed_tracedSVG
}
}
}
}
}
}
`}
render={data => {
return data.items.edges.map(item => {
return <Product key={item.node.id} product={item.node} />
})
}}
/>
</ProductList>
</Section>
)
}
const ProductList = styled.div`
margin: 3rem 0;
display: grid;
grid-template-columns: 100%;
grid-row-gap: 3rem;
#media (min-width: 576px) {
grid-template-columns: 95%;
}
#media (min-width: 776px) {
grid-template-columns: 80%;
justify-content: center;
}
#media (min-width: 992px) {
grid-template-columns: 1fr 1fr;
grid-gap: 2rem;
}
`

It seems that there's no image specified at the Contentful field. Therefore the fixed value is null and that's not allowed by their plugin gatsby-source-contentful.

In this case looks like the property img in product don't have any fixed property. In particular, img is null, and you're treating it as an object. You may have to check if img is actually an object before destructuring it

Related

What is the reason why the pagination style is not getting applied? I am trying to display lists in row but it is not working

Pagination.jsx
import { Box } from "#chakra-ui/react";
import React, { useEffect, useState } from "react";
import ReactPaginate from "react-paginate";
import "./Pagination.css";
export function ReactPagination({ lastPage, filterData }) {
const [pageCount, setPageCount] = useState(0);
useEffect(() => {
setPageCount(lastPage);
}, [lastPage]);
// Invoke when user click to request another page.
const handlePageClick = (event) => {
filterData(event.selected + 1);
};
return (
<Box w="full">
<ReactPaginate
breakLabel="..."
nextLabel="next >"
onPageChange={handlePageClick}
pageRangeDisplayed={4}
pageCount={pageCount}
previousLabel="< previous"
renderOnZeroPageCount={null}
containerClassName="pagination"
previousLinkClassName="pagination__link"
nextLinkClassName="pagination__link"
disabledClassName="pagination__link--disabled"
activeClassName="pagination__link--active"
/>
</Box>
);
}
Pagination.css
//css for react paginate
.pagination {
list-style: none;
display: flex !important;
gap: 4px;
justify-content: space-between;
background: red;
}
.pagination a {
padding: 10px;
border-radius: 5px;
border: 1px solid #6c7ac9;
color: #6c7ac9;
}
.pagination__link {
font-weight: bold;
}
.pagination__link--active a {
color: #fff;
background: #6c7ac9;
}
.pagination__link--disabled a {
color: rgb(198, 197, 202);
border: 1px solid rgb(198, 197, 202);
}
The pagination className in containerClassName is not getting applied but it's strange that other styles like disabledClassName, activeClassName are applied. I am trying to display lists in row but it is not working. Is there any reason or any package updates that is causing this issue?

Custom arrow Swiper Slider + Next.js + Sass

I'm using the slider swiper in a project developed in Next.JS and I'm using Sass to do the styling. But when I'm going to use the swiper classes, as mandated by the documentation, to style the arrows, it doesn't work.
I need the arrows to be outside the component, not overlapping.
CSS
.swiper-button-next,
.swiper-button-prev {
background: red;
position: absolute;
top: 50%;
width: calc(var(--swiper-navigation-size) / 44 * 27);
height: var(--swiper-navigation-size);
margin-top: calc(0px - (var(--swiper-navigation-size) / 2));
z-index: 10;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--swiper-navigation-color, var(--swiper-theme-color));
}
.swiper-button-next.swiper-button-disabled,
.swiper-button-prev.swiper-button-disabled {
opacity: 0.35;
cursor: auto;
pointer-events: none;
}
.swiper-button-next:after,
.swiper-button-prev:after {
background: red;
font-family: swiper-icons;
font-size: var(--swiper-navigation-size);
text-transform: none !important;
letter-spacing: 0;
text-transform: none;
font-variant: initial;
line-height: 1;
}
.swiper-button-prev,
.swiper-container-rtl .swiper-button-next {
left: 10px;
right: auto;
}
.swiper-button-prev:after,
.swiper-container-rtl .swiper-button-next:after {
content: "prev";
color: #000;
}
.swiper-button-next,
.swiper-container-rtl .swiper-button-prev {
right: 10px;
left: auto;
}
.swiper-button-next:after,
.swiper-container-rtl .swiper-button-prev:after {
content: "next";
}
.swiper-button-next.swiper-button-white,
.swiper-button-prev.swiper-button-white {
--swiper-navigation-color: #ffffff;
}
.swiper-button-next.swiper-button-black,
.swiper-button-prev.swiper-button-black {
--swiper-navigation-color: #000000;
}
.swiper-button-lock {
display: none;
}
I've tried changing the styles, but nothing reflects on the component. If I change styles by browser it works normally.
Changing the basic arrows styles is pretty simple - take a look at the following codesandbox: https://codesandbox.io/s/stoic-shaw-q35wq?file=/src/styles.scss
.swiper-button-prev, .swiper-button-next {
top: 45%;
width: 40px;
height: 40px;
background: #fff;
border: 1px solid gray;
border-radius: 50%;
color: blue;
font-weight: 700;
outline: 0;
transition: background-color .2s ease, color .2s ease;
&::after {
font-size: 16px;
}
}
.swiper-button-prev {
&:after {
position: relative;
left: -1px;
}
}
.swiper-button-next {
&:after {
position: relative;
left: 1px;
}
}
.swiper-button-prev, .swiper-container-rtl .swiper-button-next {
left: 10px;
right: auto;
}
.swiper-button-next, .swiper-container-rtl .swiper-button-prev {
right: 10px;
left: auto;
}
.swiper-button-prev.swiper-button-disabled, .swiper-button-next.swiper-button-disabled {
opacity: 0;
cursor: auto;
pointer-events: none;
}
Moving the arrows outside, however, is a bit more tricky. In the example above I've used a little CSS tricks (negative margin and corresponding padding) and some overflows to get it working but it might not be enough for your use case.
You would have to create your own next/previous elements:
import React from "react";
import { Navigation, Pagination, Scrollbar, A11y, Controller } from "swiper";
import { Swiper, SwiperSlide } from "swiper/react";
// Import Swiper styles
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
import "swiper/css/scrollbar";
import "./styles.scss";
const image = "https://source.unsplash.com/featured/300x201";
export default function App() {
const images = new Array(6).fill({ url: image });
const [swiper, setSwiper] = React.useState();
const prevRef = React.useRef();
const nextRef = React.useRef();
React.useEffect(() => {
if (swiper) {
console.log("Swiper instance:", swiper);
swiper.params.navigation.prevEl = prevRef.current;
swiper.params.navigation.nextEl = nextRef.current;
swiper.navigation.init();
swiper.navigation.update();
}
}, [swiper]);
return (
<div className="App">
<div className="carousel-container">
<div className="swiper-button" ref={prevRef}>
prev
</div>
<Swiper
modules={[Navigation, Pagination, Scrollbar, A11y, Controller]}
className="external-buttons"
spaceBetween={24}
slidesPerView={1}
navigation={{
prevEl: prevRef?.current,
nextEl: nextRef?.current
}}
updateOnWindowResize
observer
observeParents
initialSlide={2}
onSwiper={setSwiper}
>
{images.map((image, index) => (
<SwiperSlide key={index}>
<img
height="200"
width="300"
alt="img"
className="image"
src={image.url}
/>
</SwiperSlide>
))}
</Swiper>
<div className="swiper-button" ref={nextRef}>
next
</div>
</div>
</div>
);
}
Complete example - https://codesandbox.io/s/prod-darkness-o483y?file=/src/App.js
Important - the examples are using Swiper v7
Here is the best way to add custom arrows:
import React, { useRef } from "react";
// For Typescript
// import SwiperCore from "swiper";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
const SliderComponent = () => {
const swiperRef = useRef();
// For Typescript!
// const swiperRef = useRef<SwiperCore>();
const sliderSettings = {
440: {
slidesPerView: 1,
spaceBetween: 30,
},
680: {
slidesPerView: 2,
spaceBetween: 30,
},
1024: {
slidesPerView: 3,
spaceBetween: 30,
},
};
return (
<div>
<button onClick={() => swiperRef.current?.slidePrev()}>Prev</button>
<Swiper
slidesPerView={3}
breakpoints={sliderSettings}
onBeforeInit={(swiper) => {
swiperRef.current = swiper;
}}
>
<SwiperSlide>
Slide 1
</SwiperSlide>
<SwiperSlide>
Slide 2
</SwiperSlide>
<SwiperSlide>
Slide 3
</SwiperSlide>
<SwiperSlide>
Slide 4
</SwiperSlide>
<SwiperSlide>
Slide 5
</SwiperSlide>
</Swiper>
<button onClick={() => swiperRef.current?.slideNext()}>Next</button>
</div>
);
};
export default SliderComponent;
hamza liaqat's answer is correct, but for typescript you need to add
import { Swiper as SwiperCore } from 'swiper/types';

How to create multi-items slider in React?

I created a multi-items carousel and it's fetching all images from the database but only displaying 3 images. I need this carousel to display all images from the database when one click on side arrows. How can I make it work as "https://react-multi-carousel.now.sh/" this carousel? Can you help me with my custom carousel?
.home__wrapper {
.categoryslider__wrapper {
display: flex;
width: 100%;
margin-top: 15px;
visibility: visible;
opacity: 1;
transition: visibility 0s, opacity 0.05s, height 0.05s linear;
height: auto;
.category {
position: relative;
height: 14vh;
margin-bottom: 1em;
cursor: pointer;
& >img {
height: 100%;
width: 100%;
object-fit: cover;
}
p {
position: absolute;
top: 0.2em;
left: 1em;
color: rgb(255, 255, 255);
font-size: 2vh;
font-weight: 900;
letter-spacing: 0.5px;
line-height: 24px;
width: 80%;
text-align: left;
}
}
}
}
import React from 'react'
import {withRouter} from 'react-router'
import './index.scss'
import {times} from 'lodash'
import Carousel from 'react-bootstrap/Carousel'
import {Col} from 'react-bootstrap';
import {API} from '../../../constants';
class CategorySlider extends React.Component {
render() {
let {stores} = this.props;
return (
<>
<Carousel className='categoryslider__wrapper'>
{times(4, (index) => {
return (
<Carousel.Item key={index}>
{stores && stores.length && stores.map(store => {
if (store.featured_products.length){
return store.featured_products[0].image_url;
}
return stores[0].name;
}).filter(image=>image!==undefined).map((image_link, i )=> {
return (
<Col key={image_link + "" + i} className="col-4 category" >
<img src={API.files.detail.replace('/files/:fileUUID/', image_link)} alt=""></img>
<p>{stores[i].name}</p>
</Col>
)
})}
</Carousel.Item >
)
})}
</Carousel>
</>
);
}
}
export default withRouter(CategorySlider);

Why doesn't my checkboxes show up in react?

I have a problem that the Size component didn't show up on the web page. Could someone help me figure it out?
This is my file hierarchy:
components
CheckBoxes
index.js
style.css
Shelf
Filter
index.js
style.css
This is my "components/Shelf/Filter/index.js":
import React, { Component } from 'react';
import Size from '../../CheckBoxes/index';
class SizePart extends Component {
availableSizes = ['XS', 'S', 'M', 'ML', 'L', 'XL', 'XXL'];
createCheckboxes = () => {
this.availableSizes.map((size) => {
return < Size size={size}/>
});
}
render(){
return (
<div className="filters">
<h4 className="title">Sizes:</h4>
{this.createCheckboxes()}
</div>
)
}
}
export default SizePart;
This is my "components/CheckBoxes/index.js" and "components/CheckBoxes/style.css":
import React, { Component } from 'react';
import "./style.css";
const Size = props => {
return <div className='size'>{props.size}</div>
}
export default Size;
///////////////////////////////////////////////////////////////////////
.size {
background-color: rgb(223, 220, 220);
display: inline-block;
position: relative;
cursor: pointer;
font-size: 22px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
width: 35px;
height: 35px;
font-size: 0.8em;
margin-bottom: 8px;
margin-right: 8px;
border-radius: 50%;
line-height: 35px;
text-align: center;
}
.size:hover {
border: 1px solid #1b1a20;
}
You don't return your array.
createCheckboxes = () => {
return this.availableSizes.map((size) => {
return < Size size={size}/>
});
}

draft-js Cannot read property 'getIn' of undefined ( getUpdatedSelectionState )

I have this error with draft-js with draft-js-plugins-editor
STRANGE BEHAVIOR: it only happens, when I refocus to first line of editor after writing, when trying to set for eg. the header of first line to H1 it changes previous focused line
ERROR: Uncaught TypeError: Cannot read property 'getIn' of undefined
FULL ERROR:
Uncaught TypeError: Cannot read property 'getIn' of undefined
at getUpdatedSelectionState (getUpdatedSelectionState.js?a009439:34)
at getDraftEditorSelectionWithNodes (getDraftEditorSelectionWithNodes.js?a009439:37)
at getDraftEditorSelection (getDraftEditorSelection.js?a7f8e9b:35)
at editOnSelect (editOnSelect.js?a7f8e9b:32)
at DraftEditor.react.js?f8ee1ff:148
at HTMLUnknownElement.callCallback (react-dom.development.js?5f39724:542)
at Object.invokeGuardedCallbackDev (react-dom.development.js?5f39724:581)
at Object.invokeGuardedCallback (react-dom.development.js?5f39724:438)
at Object.invokeGuardedCallbackAndCatchFirstError (react-dom.development.js?5f39724:452)
at executeDispatch (react-dom.development.js?5f39724:836)
This is my component:
/* eslint-disable react/no-multi-comp */
import React, {Component} from 'react';
import sv from '../../config/styleVariables'
import Editor from 'draft-js-plugins-editor';
import {EditorState,convertToRaw} from 'draft-js'
import createToolbarPlugin from 'draft-js-static-toolbar-plugin';
import {
ItalicButton,
BoldButton,
UnderlineButton,
HeadlineOneButton,
HeadlineTwoButton,
HeadlineThreeButton,
UnorderedListButton,
OrderedListButton,
BlockquoteButton,
} from 'draft-js-buttons'
export default class TextArea extends Component {
constructor(props){
super(props)
this.state = {
editorState: EditorState.createEmpty(),
}
const toolbarPlugin = createToolbarPlugin({
structure: [
BoldButton,
ItalicButton,
UnderlineButton,
HeadlineOneButton, ,
HeadlineTwoButton,
HeadlineThreeButton,
UnorderedListButton,
OrderedListButton,
// BlockquoteButton,
]
})
const { Toolbar } = toolbarPlugin;
this.Toolbar = Toolbar
this.plugins = [toolbarPlugin];
}
onChange(editorState){
this.setState({
editorState,
})
this.props.update(JSON.stringify(convertToRaw(editorState.getCurrentContent())))
}
focus(){
this.editor.focus();
}
render() {
const {Toolbar, plugins} = this
const {name} = this.props
return (
<div className="TextArea">
{/*language=SCSS*/}
<style jsx global>{`
.TextArea .headlineButtonWrapper {
display: inline-block;
}
.TextArea {
background: ${sv.white};
}
.TextArea > div>div:first-child {
display: flex;
padding: 0 0 .25em 0;
border-bottom: 1px solid ${sv.border};
}
.TextArea > div>div:first-child>div button{
background: transparent;
cursor: pointer;
border: none;
display: flex;
align-items: center;
justify-content: center;
width: 3em;
height: 2.5em;
font-size: .8em;
margin-right: .2em;
}
.TextArea > div>div:first-child>div button:hover {
background: ${sv.extraLight};
color: ${sv.primary};
}
.TextArea .DraftEditor-root {
padding: 0 .5em;
cursor: text;
}
.TextArea .headlineButton {
background: #fbfbfb;
color: #888;
font-size: 18px;
border: 0;
padding-top: 5px;
vertical-align: bottom;
height: 34px;
width: 36px;
}
.TextArea .headlineButton:hover,
.TextArea .headlineButton:focus {
background: #f3f3f3;
}
`}
</style>
<div onClick={this.focus.bind(this)}>
<Toolbar key={name} />
<Editor
editorState={this.state.editorState}
onChange={this.onChange.bind(this)}
plugins={plugins}
ref={(element) => {
this.editor = element
}}
/>
</div>
</div>
);
}
}
My component looks like this:
I meet the same problem. It looks like because call editorState.getBlockTree(anchorBlockKey).getIn(...) in getUpdatedSelectionState.js the editorState.getBlockTree(anchorBlockKey) is undefined whenever the block type is unstyled.
I have no idea how to fix it, so make a work around solution like this:
const headerOne = '<h1>Title</h1>';
const blocksFromHTML = convertFromHTML(headerOne);
const state = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = {
editorState: EditorState.createWithContent(state)
}
But there will be another problem when you press enter new line will be H1 either.

Resources