skip to Main Content

am trying to create a slider with nexjs and type script , but am getting below error when am destructing an array of object

Server Error

TypeError: Cannot destructure property ‘image’ of ‘sliderItem[index]’ as it is undefined.
This error happened while generating the page. Any console logs will be displayed in the terminal window.
Source

components/Slider/Slider.tsx (53:10) @ image

51 | };
52 |

53 | const { image, name, title, quote } = sliderItem[index];

import Image from 'next/image';
import React, { useEffect, useState } from 'react';
import { MdArrowForwardIos, MdArrowBackIosNew } from 'react-icons/md';
const url = 'http://localhost:3004/people';
export type SliderProps = {
  id: number;
  image: string;
  name: string;
  title: string;
  quote: string;
};

function Slider() {
  const [index, setIndex] = useState<number>(0);
  const [sliderItem, setSliderItem] = useState<SliderProps[]>([]);

  const fetchData = async () => {
    const res = await fetch(url);
    const data = await res.json();
    setSliderItem(data);
  };

  useEffect(() => {
    fetchData();
  }, []);

  useEffect(() => {
    setInterval(() => {
      if (index === sliderItem.length - 1) {
        setIndex(0);
      } else {
        setIndex(index + 1);
      }
    }, 300000);
  }, [index, sliderItem]);

  const slideLeft = () => {
    if (index === 0) {
      setIndex(sliderItem.length - 1);
    } else {
      setIndex(index - 1);
    }
  };
  const slideRight = () => {
    if (index === sliderItem.length - 1) {
      setIndex(0);
    } else {
      setIndex(index + 1);
    }
  };

  const { image, name, title, quote } = sliderItem[index];
  return (
    <div className='max-w-5xl mx-auto '>
      <div className='grid grid-cols-1 mt-20 place-items-center'>
        <div className='flex flex-col items-center justify-center max-w-3xl gap-2 '>
          <div className='w-32 p-1 rounded-full bg-violet-200'>
            <img
              src={image}
              alt={title}
              className='object-cover w-32 h-32 rounded-full '
            />
          </div>
          <div className='flex items-center justify-between w-full gap-5 '>
            <button onClick={slideLeft} className='items-center text-3xl'>
              <MdArrowBackIosNew />
            </button>
            <div>
              <h3 className='text-3xl text-center text-violet-800'>{name}</h3>
              <h4 className='text-center '>{title}</h4>
            </div>
            <button onClick={slideRight}>
              <MdArrowForwardIos />
            </button>
          </div>
          <p className='text-center '>{quote}</p>
        </div>
      </div>
    </div>
  );
}
export default Slider;

2

Answers


  1. Chosen as BEST ANSWER
    Thanks ,
    
    this how i resolved the issue
    
    
    
    import Image from 'next/image';
    import React, { useEffect, useState } from 'react';
    import { MdArrowForwardIos, MdArrowBackIosNew } from 'react-icons/md';
    const url = 'http://localhost:3004/people';
    export type SliderProps = {
      id: number;
      image: string;
      name: string;
      title: string;
      quote: string;
    };
    
    function Slider() {
      const [index, setIndex] = useState<number>(0);
      const [sliderItem, setSliderItem] = useState<SliderProps[]>([]);
    
      const fetchData = async () => {
        const res = await fetch(url);
        const data = await res.json();
        setSliderItem(data);
      };
    
      useEffect(() => {
        fetchData();
      }, []);
    
      const slideRight = () => {
        setIndex((oldIndex: number) => {
          let index = oldIndex + 1;
          if (index > sliderItem.length - 1) {
            index = 0;
          }
          return index;
        });
      };
    
      const slideLeft = () => {
        setIndex((oldIndex: number) => {
          let index = oldIndex - 1;
          if (index < 0) {
            index = sliderItem.length - 1;
          }
          return index;
        });
      };
    
      useEffect(() => {
        let slider = setInterval(() => {
          setIndex((prevIndex) => {
            let index = prevIndex + 1;
            if (index > sliderItem.length - 1) {
              index = 0;
            }
            return index;
          });
        }, 3000);
    
        return () => clearInterval(slider);
      }, [index, sliderItem.length]);
      return (
        <div className='max-w-5xl mx-auto '>
          <div className='grid grid-cols-1 mt-20 place-items-center'>
            <div className='flex flex-col items-center justify-center max-w-3xl gap-2 '>
              <div className='w-32 p-1 rounded-full bg-violet-200'>
                <img
                  src={sliderItem[index]?.image}
                  alt={sliderItem[index]?.title}
                  className='object-cover w-32 h-32 rounded-full '
                />
              </div>
              <div className='flex items-center justify-between w-full gap-5 '>
                <button onClick={slideLeft} className='items-center text-3xl'>
                  <MdArrowBackIosNew />
                </button>
                <div>
                  <h3 className='text-3xl text-center text-violet-800'>
                    {sliderItem[index]?.name}
                  </h3>
                  <h4 className='text-center '>{sliderItem[index]?.title}</h4>
                </div>
                <button onClick={slideRight}>
                  <MdArrowForwardIos />
                </button>
              </div>
              <p className='text-center '>{sliderItem[index]?.quote}</p>
            </div>
          </div>
        </div>
      );
    }
    export default Slider;
    
    enter code here
    

  2. on the very first render sliderItem is empty array, as passed in useState.
    So there is no item even on index=0. You could show some kind of spinner, while the data is loading, or, if you have no particular pattern to handle loading in the application, the easiest fix would be to just return null before your line with destructuring

    if(sliderItem.length === 0) {
       return null;
    }
    const { image, name, title, quote } = sliderItem[index];
    return (
      <div className='max-w-5xl mx-auto '>
      ....
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search