0

I'm building a puzzle application that when completed, will play a video.

When I complete the puzzle, everything changes and it works fine but I get the following error in the console and I'm not sure what I need to do to fix it.

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method

Apologies if this is an easy question, I'm self taught so I know I've got some gaps in my knowledge. Does anyone know how I can fix this error?

I'd really appreciate any help that anyone can give.

import React, { Component } from 'react'
import styled from 'styled-components';
import { DragDropContainer, DropTarget } from 'react-drag-drop-container';

import VideoMov from '../../videos/vid.mov'; 
import VideoWebm from '../../videos/vid2.webm';

import "./puzzle.css";

export class Game extends Component {

    state = {
        video: false,
    }

    PuzzleContainer = styled.div`
        display: flex;
        flex-direction: column;
        margin-top: 50px;
    `;
        
    PuzzleBoard = styled.div`
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
    `;
    
    PuzzleBoardTop = styled.div`
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
        margin-bottom: 60px;        
    `;

    PuzzleBoardPieces = styled.div`
        height: 50vw; 
        max-height: ${ ({ height }) => height ? height + "px" : "210px" };
        width: ${ ({ width }) => width ? width + "px" : "85px" }; 
        border: 1px solid #fff;
        background-color: ${ ({ color }) => color ? '#' + color : "transparent" };
        margin-right: ${ ({ margin }) => margin ? "60px" : "0px" }
    `;

    PuzzleBoardBottom = styled.div`
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
        flex-wrap: wrap;
        width: 100%;    
    `;

    VideoWrapper = styled.div`
        width: 100%;
        height: 100%;
        margin-top: 50px;
        position: fixed;
        top: 0;
        left: 0;
        video {
            height: 100%;
            width: 100%;
        }
    `;
    
    PuzzleCounter = 0;

    dropped = e => {
        e.containerElem.style.visibility = 'hidden';
        e.target.classList.add('highlighted');
        this.PuzzleCounter++;

        if (this.PuzzleCounter === 3) {
            this.setState({
                video :  true,
            });
        }
    }

    PuzzleGame = (
            <this.PuzzleBoard>

                <this.PuzzleBoardTop>
                    <DropTarget 
                        targetKey="piece-7314" 
                        dropData={ 
                            { name : 'left' }
                        }
                        onHit={ this.dropped }
                    >
                        <this.PuzzleBoardPieces className="puzzle-board left" />
                    </DropTarget>
                    <DropTarget 
                        targetKey="piece-3167" 
                        dropData={ 
                            { name : 'middle' }
                        }
                        onHit={ this.dropped }
                    >
                        <this.PuzzleBoardPieces className="puzzle-board middle" height={ 150 } width={ 90 } />
                    </DropTarget>
                    <DropTarget 
                        className="drop-container drop-container-right"
                        targetKey="piece-5149" 
                        dropData={ 
                            { name : 'right' }
                        }
                        onHit={ this.dropped }
                    >
                        <this.PuzzleBoardPieces className="puzzle-board right" />
                    </DropTarget>
                </this.PuzzleBoardTop>

                <this.PuzzleBoardBottom>
                    <DragDropContainer targetKey="foo">
                        <this.PuzzleBoardPieces className="puzzle-piece left" color="09203f" height={ 210 } width={ 170 } margin={ true } />
                    </DragDropContainer>
                    <DragDropContainer targetKey="foo">
                        <this.PuzzleBoardPieces className="puzzle-piece middle" color="0a4ba6" height={ 210 } width={ 90 } margin={ true } />
                    </DragDropContainer>
                    <DragDropContainer 
                        targetKey="piece-7314"
                        dragData={
                            { label : 'left' }
                        }
                    >
                        <this.PuzzleBoardPieces className="puzzle-piece left" color="118ab6" margin={ true } />
                    </DragDropContainer>
                    <DragDropContainer targetKey="foo">
                        <this.PuzzleBoardPieces className="puzzle-piece right" color="173966" height={ 215 } width={ 70 } margin={ true } />
                    </DragDropContainer>
                    <DragDropContainer 
                        targetKey="piece-3167" 
                        dragData={
                            { label : 'middle' }
                        }
                    >
                        <this.PuzzleBoardPieces className="puzzle-piece middle" color="052651" height={ 150 } width={ 90 } margin={ true } />
                    </DragDropContainer>
                    <DragDropContainer 
                        targetKey="piece-5149" 
                        dragData={
                            { label : 'right' }
                        }
                    >
                        <this.PuzzleBoardPieces className="puzzle-piece right" color="092c65" margin={ false } />
                    </DragDropContainer>
                </this.PuzzleBoardBottom>

            </this.PuzzleBoard>
    );

    VideoContainer = (
        <this.VideoWrapper>
            <video autoPlay muted playsInline onEnded={ () => console.log('video ended') }>
                <source src={ VideoMov } type='video/mp4; codecs="hvc1"' />
                <source src={ VideoWebm } type="video/webm" />
            </video>
        </this.VideoWrapper>
    );

    render() {

        const { video } = this.state;
        return (
            <this.PuzzleContainer>
                { !video ? this.PuzzleGame : this.VideoContainer }
            </this.PuzzleContainer>
        );

    }
}

export default Game

  • What is `this.props.completeFunction('complete')` this function doing? Show code in this function – sojin Oct 25 '21 at 12:24
  • What is this line doing `PuzzleCounter = 0;`? – k-wasilewski Oct 25 '21 at 12:40
  • Hi @sojin, thanks for responding. this.props.completeFunction('complete') was left in there by accident. That updates the parent container and tells it to move on to the next page (not causing the issue unfortunately otherwise that would be easier for me to remove and fix). – Thomas Hewitt Oct 25 '21 at 14:05
  • Hi @k-wasilewski, the PuzzleCounter = 0; is an iterator that updates every time a puzzle piece has successfully been added to the correct puzzle slot. Once all three have been added successfully, the function moves onto the next stage which is to update the state of video to true. – Thomas Hewitt Oct 25 '21 at 14:07

0 Answers0