Johnny Bravo
Johnny Bravo

Reputation: 173

Setting state without re-rendering with useEffect not working

I simply need my state value to change based on screen sizing live time. Even though my screen size changes, my count value stays the same unless I reload the page. this needs to update live for better responsive design. Here is my code. Thanks!

import React, { useState, useEffect } from 'react';
import Carousel from '@brainhubeu/react-carousel';
import '@brainhubeu/react-carousel/lib/style.css';
import { useMediaQuery } from 'react-responsive'

const MyCarousel = () => {

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

    const [count, setCount] = useState(0);

    const loadMediaQuery = () =>{
        if (tablet)
            setCount(1)
        if (phone)
            setCount(2)
        if (desktop)
            setCount(3)
    }

    const tablet = useMediaQuery({
        query: '(max-width:  876px)'
    })
    const phone = useMediaQuery({
        query: '(max-width:  576px)'
    })
    const desktop = useMediaQuery({
        query: '(min-width:  876px)'
    })

    return (
        <div>
            <Carousel slidesPerPage={count} >
            <img className="image-one"/>
            <img className="image-two"/>
            <img className="image-three"/>
            </Carousel>
      </div>
    );
}

Upvotes: 0

Views: 1805

Answers (3)

dillon
dillon

Reputation: 69

Expanding on the custom hook provided in this answer, you can do something like

const [width, height] = useWindowSize();

useEffect(() => {
  loadMediaQuery();
}, [width]);

That useEffect function says: Execute loadMediaQuery() every time the value of width changes.

Upvotes: 0

Mohamed Magdy
Mohamed Magdy

Reputation: 605

That's because your useEffect has no dependencies so it loads one time only after the component has been mounted. To fix that you should have the following code:

import React, { useState, useEffect } from 'react';
import Carousel from '@brainhubeu/react-carousel';
import '@brainhubeu/react-carousel/lib/style.css';
import { useMediaQuery } from 'react-responsive';

const MyCarousel = () => {

  const tablet = useMediaQuery({
    query: '(max-width:  876px)'
  });

  const phone = useMediaQuery({
    query: '(max-width:  576px)'
  });

  const desktop = useMediaQuery({
    query: '(min-width:  876px)'
  });

  useEffect(() => {
    loadMediaQuery();
  }, [tablet, phone, desktop]);

  const [count, setCount] = useState(0);

  const loadMediaQuery = () =>{
    if (tablet)
      setCount(1)
    else if (phone)
      setCount(2)
    else if (desktop)
      setCount(3)
    }

    return (
      <div>
        <Carousel slidesPerPage={count} >
          <img className="image-one"/>
          <img className="image-two"/>
          <img className="image-three"/>
         </Carousel>
       </div>
    );
  }

Upvotes: 1

Charef B
Charef B

Reputation: 437

useEffect means: runs the callback function that's passed to useEffect after this component is rendered, and since you passed an empty array as the 2nd argument, it means useEffect is executed once, only the first time when this component gets rendered (and not when the state changes) , since your function call is inside useEffect, it will work only when you reload the page, you can either add the variables to the empty array like Mohamed Magdy did, or simply call loadMediaQuery again outside useEffect

Upvotes: 1

Related Questions