Search code examples
javascriptreactjslogic

In React.js, how can I code the logic of aomw buttons considering that this.setState doesnt' update anything until it is passed into another function?


I am working on this so-called webpage and have several "tiles" arranged in a table-like form. When a tile is clicked and it is an image, it is supposed to be replaced by a <p> element, and when a tile is clicked and it is a paragraph, it is supposed to be replaced by an <img>. However, no two tiles can show <p> elements at the same time.

    handleClickTile(e) {
        const newTarget = e.target

        // if (this.state.clickedTarget !== newTarget) {
            // const stateClickedTgt = tgt
        if(this.state.mode === 'p') {
            if(newTarget !== this.state.clickedTarget) {
                console.log("IS new target different from old? ")
                this.setState({ mode: 'image' })
                this.setState({ clickedTarget: newTarget})
            } else {
                this.setState({ mode: 'image' })
                this.setState({ clickedTarget: newTarget })
            }
        } 
        // else {
        //     this.setState({ mode: 'p', clickedTarget: newTarget })
        // }
        if(this.state.mode === 'image') {
            this.setState({ clickedTarget: newTarget, mode: 'p' })
            // this.setState()
        }

        // } 
        // else {
        //     console.log("THE ELSE -- this.state.clicked is not newtgt ")
        //     this.state.mode === 'image'
        //     ? this.setState({ mode: 'p', clickedTarget: newTarget }) 
        //     : this.setState({ mode: 'image', clickedTarget: newTarget })
        // }

    }

As you can tell by the commenting and messy code, I have had several attempts at cracking the logic of this, but haven't gotten far. The problem I see is that this.setState() only updates anything once it is used in the render function, which is after handleClickTile() ends. This creates a problem in "resetting" the tiles so that no two tiles show <p> elements at the same time. At least, resetting the tiles to <img> when clicked is the approach I have taken, and I can't surmise any other ways, which is why I'm asking for help.


Solution

  • I would implement the componentDidUpdate() lifecycle method in your component class to compare the previous state with your current state after updating your state properties in handleClickTile().

    When the condition that certain previous state properties and their corresponding current state properties don't match is met (i.e. this.state.mode or this.state.clickedTarget), then you can update the other state properties which will effectively "reset" your tiles.

    So it would look something like:

    componentDidUpdate(prevProps, prevState) {      
      if (prevState.mode !== this.state.mode) { // or replace mode with the appropriate state property to check for
        this.setState({ stateProp: newValue }) // change whatever state properties you need to reset the other tiles
      }  
    }

    Here's more information on componentDidUpdate() from the React documentation.

    You want to be sure to check that the appropriate state properties don't match between the previous and current state if you are going to set the state in this lifecycle method, in order to avoid an infinite loop (as mentioned in the documentation).