Home > Software design >  Trying to Iterate through "Fetch" JSON Data after assigning to State in React.js for a &qu
Trying to Iterate through "Fetch" JSON Data after assigning to State in React.js for a &qu

Time:04-20

pretty new to React so don't clown me to hard haha.

Essentially my goal is to fetch the data from my personal JSON server & render that data onto a "Slider" that I am creating.

I am following along with a tutorial and decided to give myself a challenge, the only difference is that where he just imported a data.js file with his data, I wanted to use JSON data / server instead.

The issues is that I'm not sure how to ".map()" through the data for each slide and render to the slider. I have a general idea of how but I'm not fully sure how to implement it correctly in the context of using JSON data with fetch requests.

I have fetched my JSON url and used .thens to string my responses & assign the data to a state setter function. When I console.log the data I receive the object successfully but twice.

Read online that I could use the first variable of state to .map(), attempted and has not worked.

Sorry if this has been touched on before, I have tried everything to find this info before asking but to no avail.

The error I receive is in regards to me using the state variable "slideIndx.map" not being a function.

What can I do here?

import {useState, useEffect} from 'react';
import { ArrowLeftOutlined, ArrowRightOutlined } from "@material-ui/icons";

import styled from "styled-components";

const Container = styled.div`
    width: 100%;
    height: 95vh;
    display: flex;
    // background-color: #b3f0ff;
    position: relative;
    overflow: hidden;
`;
const Arrow = styled.div`
    width: 50px;
    height: 50px;
    background-color: #e6ffff;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 0;
    bottom: 0;
    left: ${props => props.direction === "left" && "10px"};
    right: ${props => props.direction === "right" && "10px"};
    margin: auto;
    cursor: pointer;
    opacity: 0.5;
    z-index: 2;
`;
const Wrapper = styled.div`
    height: 100%;
    display: flex;
    transform: translateX(0vw)
`
const Slide = styled.div`
    width: 100vw;
    height: 100vw;
    display: flex;
    align-items: center;
    background-color: ${props => props.bg};
`
const ImgContainer = styled.div`
    height: 100%;
    flex:1;
`
const Image = styled.img`
    padding-left: 30px;
    align-items: left;
`
const InfoContainer = styled.div`
    height: 80%;
    flex:1;
    padding: 30px;
`
const Title = styled.h1`
    font-size: 50px
`
const Desc = styled.p`
    margin: 50px 0px;
    font-size: 20px;
    font-weight: 500;
    letter-spacing: 3px;
`
const Button = styled.button`
    padding: 10px;
    font-size: 20px;
    background-color: transparent;
    cursor: pointer;
`


const Slider = () => {
    const [slideIndx, setSlideIndx] = useState(0);

    const fetchSliderItems = () => {
        fetch('http://localhost:3000/sliderItems')
        .then(resp => resp.json())
        .then(data => {
            console.log(data)
            setSlideIndx(data)
        })
    }

    useEffect(() => {fetchSliderItems()}, [])


    const handleClick = (direction) => {}

  return (
    <Container>
        <Arrow direction="left" onClick={() => handleClick("left")}>
            <ArrowLeftOutlined />
        </Arrow>
        // Here is where I am attempting to map over the items.
        <Wrapper>
        {fetchSliderItems.map((item) => (
            <Slide bg={item.bg}>
            <ImgContainer>
                <Image src={item.img}/>
            </ImgContainer>
            <InfoContainer>
                <Title>{item.title}</Title>
                <Desc>{item.desc}</Desc>
                <Button>SHOP NOW</Button>
            </InfoContainer>
            </Slide>
        ))}
        </Wrapper>

        <Arrow direction="right" onClick={() => handleClick("right")}>
            <ArrowRightOutlined />
        </Arrow>

    </Container>
  )
}

export default Slider
{
  "sliderItems": [

    {
        "id": 1,
        "img": "../images/model1.png",
        "title": "SPRING CLEANING",
        "desc": "DONT MISS OUR BEST COLLECTION YET! USE #FLATIRON10 TO RECEIVE 10% OFF YOUR FIRST ORDER",
        "bg": "b3ecff"
      },
      {
        "id": 2,
        "img": "https://i.ibb.co/DG69bQ4/2.png",
        "title": "SHOW OFF HOW YOU DRESS",
        "desc": "WITH OUR HUGE SELECTION OF CLOTHES WE FIT ALL YOUR STYLING NEEDS",
        "bg": "ccf2ff"
      },
      {
        "id": 3,
        "img": "../images/model1.png",
        "title": "POPULAR DEALS",
        "desc": "RECEIVE FREE SHIPPING ON ALL ORDERS OVER $50!",
        "bg": "fe6f9ff"
      }
  ]
}

CodePudding user response:

You should share the error you're getting. But based on the second screenshot, it looks like your array is wrapped in a sliderItems object.

You want a raw array when you .map. So maybe try setting your slideIndx to the raw array by doing something like:

setSlideIndx(data.sliderItems)

Try confirming the shape of your state by console logging above your return with:

console.log(slideIndx)

CodePudding user response:

You're calling map from fetchSliderItems.map, but fetchSliderItems is a function, not an array. You need to call map from the array containing the data, which in your case is slideIndx.sliderItems.

What happens in your code is const [slideIndx, setSlideIndx] = useState(0); initializes slideIndx to 0. When useEffect runs fetchSliderItems, you'll fetch the data and eventually the line setSlideIndx(data) assigns data to slideIndx. Because your data is an object that holds and array in the sliderItems property, the array can now be accessed in slideIndx.sliderItems.

So fist thing you should do to fix it is change the useState line to const [slideIndx, setSlideIndx] = useState([]);, because you want your state variable to be an array. Then when you fetch the data you want to call setSlideIndx(data.sliderItems) to assign your data to slideIndx. Finally, in your jsx return you should use slideIndx.map.

  • Related