How to pass two state variables into the same React useState? - Array & Integer

Viewed 333

Working on an e-commerce store project where I have a Slider component.

I am fetching my own JSON data from a localhost server & mapping over the array for each slide.

My goal is to find a way to use the same useState() to render the items onto the page & click a button to move to the next slide.

I have tried to do something like useState([], 0) One for my array & another one to change index on button click however this did not work lol...

The array is of course for the data to be displayed however the tricky part for me is figuring out a way to move to the next page.

I am trying to use transform:translateX in my Wrapper styled component and attempting to pass props in so I can change the slide to the next slide and still render the data on the page.

How can I go about using state in this way described above based on my code?

*** Before reading the code snippets, my current code shows that I have tried creating two states, and passing the second state with my integer into my fetch request, no errors pop up but it doesn't work obviously as it doesn't have an array of items to index through.

In the code snippet I have included the code for the entire slider & also the information inside my data.json file.

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;s
`;
    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({props => props.arrowIndx * -100}vw);
`
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([]);
    const [arrowIndx, setArrowIndx] = useState(0);

    const handleClick = (direction) => {

        if(direction === "left"){
            setArrowIndx(arrowIndx > 0 ? arrowIndx - 1 : 2)
        } else{
            setArrowIndx(arrowIndx < 2 ? arrowIndx + 1 : 0)
        }
    }


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


  return (
    <Container>
        <Arrow direction="left" onClick={() => handleClick("left")}>
            <ArrowLeftOutlined />
        </Arrow>
        <Wrapper arrowIndx={arrowIndx}>
        {slideIndx.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": "../images/model2.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/model3.png",
        "title": "POPULAR DEALS",
        "desc": "RECEIVE FREE SHIPPING ON ALL ORDERS OVER $50!",
        "bg": "#fe6f9ff"
      }
  ]
}

1 Answers

if you want to use 2 data at 1 use state you have 2 way to achieve that

  1. store data as cell of array like below.

    const [data,setData] = useState([1,2])
    console.log(data[1])
    
  2. set data as Object in useState

    const [data,setData] = useState({data1: 1, data2: 2 })
    

but i suggest you to use second approach because it's easy to use. one point you must have care about it in this approach is, if you want to update state with object-state you have to update state with deep copy and then react can re-render component for example if you want to update data2 in object of state you have to dod this

const [data,setData] = useState({data1: 1, data2: 2 })

setData((prevState) => ({
    ...prevState,
    data2: 'value',
}));

white this snippet you will get update data2 and react get re-render

in your case if you want save array and update it and if you want get re-render when pass new array you have to clone new array and pass it into useState and you can archive this with spread operator in JavaScript. Example:

setData((prevState) => ({
    ...prevState,
    data2: [...newArray],
}));

if you pass newArray instead of [...newArray] you just pass the reference of memory if array into state and if after setState you change newAereay at the rest of code your state will update to and you don't want this.

Related