React JS Lifecycle Problem

Asked

Viewed 56 times

1

Good night!

I’m in the development of a page that has three buttons.

The first button (Publications) renders this content: inserir a descrição da imagem aqui

The second Button(Jorys) renders this second content: inserir a descrição da imagem aqui

And the third button(Suggestions) renders this third empty content (for now): inserir a descrição da imagem aqui

NOTE: Whenever you click on a button the React-route changes the path:

  • Being /explorer for Publication;
  • /jorys to Jorys and;
  • /sugestions for the Sugestions.

The idea is to make every time a button is clicked a class called active be added to the link on that button (and consequently remove that class from the other buttons if they have it) for the purpose of a custom css on the custom button!

I was able to implement the logic behind it, but I’m having trouble making it work in practice because every time I change the state for setState(), the update (i.e., the addition of the class) only comes on the next mount! Even if I use componentDidUpdate() not of the result...

I’ll leave the code below:

import React, { Component } from 'react'
import {Box, Grid } from "@chakra-ui/react"
import TabExplorer from './TabExplorer'
import TabWorks from './TabWorks'
import {Link, BrowserRouter as Router, Switch, Route} from 'react-router-dom'


export default class Tabs extends Component {

    constructor(props){
        super(props)
        this.isClicked = this.isClicked.bind(this)
        this.updateClass = this.updateClass.bind(this)

        this.state = {
            explorer: true,
            jorys: false,
            sugestions: false
        }
    }

    componentDidMount() {
        this.isClicked()
        this.updateClass()
    }

    componentWillUnmount() {
        this.isClicked()
        this.updateClass()
    }

    componentDidUpdate() {
        this.updateClass()
    }
    UNSAFE_componentWillUpdate(){
        this.updateClass()
    }

    isClicked() {
        const stateHere = this.state
        const path = window.location.pathname
        switch(path){
            case '/explorer':
                stateHere.explorer = true
                stateHere.jorys = false
                stateHere.sugestions = false
            break
            case '/jorys':
                stateHere.jorys = true
                stateHere.explorer = false
                stateHere.sugestions = false
            break
            case '/sugestions':
                stateHere.sugestions = true
                stateHere.jorys = false
                stateHere.explorer = false
            break
            default:
            break
        }
        return this.setState({state: stateHere})
    }

    updateClass() {
        const explorer = document.getElementById('explorer')
        const jorys = document.getElementById('jorys')
        const sugestions = document.getElementById('sugestions')
        this.state.explorer ? explorer.classList.add('active') : explorer.classList.remove('active')
        this.state.jorys ? jorys.classList.add('active') : jorys.classList.remove('active')
        this.state.sugestions ? sugestions.classList.add('active') : sugestions.classList.remove('active')
    }
    
    render() {
        return (
            <React.Fragment>
                <Router>
                    <Box as='main'>
                        <Grid
                            gridTemplateColumns='22% 50% 28%'
                            gridAutoRows='40px 100vh'
                            gridTemplateAreas="'. tab .' 'content content content'">
                            <Box
                                as='div'
                                gridArea='tab'
                                m='auto'
                                display='flex'
                                flexDirection='row'>
                                <Link to='/explorer' onClick={(e) => this.isClicked(e)}>
                                    <Box
                                        id='explorer'
                                        p='5px'
                                        fontFamily='Open Sans, sans-serif'
                                        fontWeight='medium'
                                        fontSize='14px'
                                        color='black'
                                        _active={{ color: "#C2383A", bg: "transparent"}} 
                                        _focus={{border: 'none'}} >
                                            Publicações
                                    </Box>
                                </Link>
                                <Link to='/jorys' onClick={(e) => this.isClicked(e)}>
                                    <Box
                                        id='jorys'
                                        p='5px' 
                                        fontFamily='Open Sans, sans-serif'
                                        fontWeight='medium'
                                        fontSize='14px'
                                        color='black'
                                        _selected={{ color: "#C2383A", bg: "transparent"}} 
                                        _focus={{border: 'none'}}>
                                            Jorys
                                    </Box>
                                </Link>
                                <Link to='/sugestions' onClick={(e) => this.isClicked(e)}>
                                    <Box
                                        id='sugestions'
                                        p='5px' 
                                        fontFamily='Open Sans, sans-serif'
                                        fontWeight='medium'
                                        fontSize='14px'
                                        color='black'
                                        _selected={{ color: "#C2383A", bg: "transparent"}} 
                                        _focus={{border: 'none'}}>
                                        Sugestões
                                    </Box>
                                </Link>
                            </Box>
                            <Box 
                                gridArea='content'
                                display='flex'
                                justifyContent='center'
                                alignItems='flex-start'>

                                <Switch>
                                    <Route path='/explorer'>
                                        <TabExplorer/>
                                    </Route>
                                    <Route path='/jorys'>
                                        <TabWorks/>
                                    </Route>
                                </Switch>
                                
                            </Box>
                        </Grid>
                    </Box>
                </Router>
            </React.Fragment>
        )
    } 
}

Can someone help me??

1 answer

1

Since you’re using the React Router lib, you don’t need to control active links if you use the Navlink.

A special version of the that will add styling Attributes to the rendered element when it Matches the Current URL.

It already does all the styling control if the "case" component with the URL passed.

For example:

<NavLink to="/explorer" activeStyle={{ color: "#C2383A", textDecoration: "none" }}>
    <Box
        id="explorer"
        p="5px"
        fontFamily="Open Sans, sans-serif"
        fontWeight="medium"
        fontSize="14px"
        _focus={{ border: "none" }}
    >
        Publicações
    </Box>
</NavLink>

You can use both the property activeClassName as to the activeStyle.

I created a functional example with the code you passed: https://codesandbox.io/s/boring-wood-3e1uq?file=/src/App.js

  • That’s exactly what I needed! Thank you very much!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.