BqZz
BqZz

Reputation: 33

Functionality of state is destroyed by another state?

Functionality of the code and the problem

In the useEffect hook I added to the div of className imageContainer onClick function which whenever is used triggers saveStyle function. The goal of saveStyle function is changing styles of elements and adding to existing array state URLs of images. Without any reason setImages hook doesn't save URLs.

My attemptions to solve this problem:

I tried to wait for a little bit because of asynchronous nature of state for example using setTimeout but it didn't work.

I also found out that whenever I delete setting of state which is called particularData and transform a little bit code ( adding manually images with particular source code in div with id dataDisplay ) then functionality of saveStyle functions works perfectly.

Is there any possibility that one state can block another state? I searched about it and all I found out was that one state can be overloaded with too much data and it can block functionality of another state, but I edited data which is passed to first state (particularData) as much as I can just to not block second state (images) but it also didn't work.

const DataDisplay = (props) =>  {
    const [images, setImages] = useState([]);
    const [particularData, setParticularData] = useState([]);

    const saveStyle = (element) => {
        
        const parentOfElement = element.target.parentNode;
        const image = parentOfElement.children[0];

        image.style.animation = "rotation 1s forwards";

        const backgroundDiv = parentOfElement.children[1];

        backgroundDiv.style.animation = "disappear 1s forwards";

        const questionMark = parentOfElement.children[2];

        questionMark.style.animation = "disappear 0.2s forwards";
        setImages([...images, image.src]);
        checkSimilarity();
    }

    const checkSimilarity = () => {
        console.log(images);
    }


    useEffect(() => {

        const dataArray = [...props.data, ...props.data];
        
        const preparedData = dataArray.map((item, index) => {
            return ( <div className="imageContainer" onClick={(element) => saveStyle(element)}>
                        <img className="photo photographyPart" alt={item.alt} src={item.link}></img>
                        <div className="backgroundDiv photographyPart"></div>
                        <img className="askSign photographyPart" src={sign} alt="Question mark" ></img>
                    </div> )
        });
        console.log(preparedData);
        setParticularData(preparedData);
    }, [ props ]);

    return (
        <div id="container">
            <div id="top"></div>
            <div id="left-side"></div>
            <div id="dataDisplay">{particularData}</div>
            <div id="right-side"></div>
            <div id="bottom"></div>
        </div>
    )
}

Upvotes: 3

Views: 59

Answers (1)

Ben Stephens
Ben Stephens

Reputation: 3371

console.log(images); in saveStyle isn't going to notice the change as setImages will queue an update to be run after saveStyle finishes. If you move console.log(images); out of saveStyle into the main part of DataDisplay you should better be able to see what's going on.

images in saveStyle may be a stale closure if so, you might be able to fix it by using a functional update for the set images call.

e.g.

setImages(prevImages => [...prevImages, image.src]);

const DataDisplay = (props) =>  {
  const [images, setImages] = React.useState([]);
  const [particularData, setParticularData] = React.useState([]);
  
  console.log(images);
  
  const saveStyle = (element) => {
    const parentOfElement = element.target.parentNode;
    const image = parentOfElement.children[0];

    image.style.animation = "rotation 1s forwards";

    const backgroundDiv = parentOfElement.children[1];

    backgroundDiv.style.animation = "disappear 1s forwards";

    const questionMark = parentOfElement.children[2];

    questionMark.style.animation = "disappear 0.2s forwards";
    setImages(prevImages => [...prevImages, image.src]);
  };

  React.useEffect(() => {
    const dataArray = [...props.data];

    const preparedData = dataArray.map((item, index) => {
      return ( <div key={item.src} className="imageContainer" onClick={(element) => saveStyle(element)}>
        <img className="photo photographyPart" alt={item.alt} src={item.link}></img>
        <div className="backgroundDiv photographyPart"></div>
        <img className="askSign photographyPart" src={item.src} alt="Question mark" ></img>
      </div> );
    });
    // console.log(preparedData);
    setParticularData(preparedData);
  }, [ props ]);

  return (
    <div id="container">
      <div id="top"></div>
      <div id="left-side"></div>
      <div id="dataDisplay">{particularData}</div>
      <div id="right-side"></div>
      <div id="bottom"></div>
    </div>
  );
}

const App = () => {
  return <DataDisplay
    data={[
      { alt: 'a', link: '#1', src: 'src1' },
      { alt: 'b', link: '#2', src: 'src2' },
      { alt: 'c', link: '#3', src: 'src3' },
    ]}
  />;
};

ReactDOM.render(<App />, document.getElementById('root'));
.imageContainer {
  display: inline-block;
  margin-right: 10px;
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>

Upvotes: 1

Related Questions