Search code examples
javascriptreactjsstyled-components

Submitted property won't update after onClick event is fired


I think that my Styled Component won't update when the onClick event is fired.

Setting the variable statically on true did show what it should have shown. I tried to console.log() the variable what I'm updating and that is doing its work as I expected.

  • passing collapsedMenuIsActive to <StyledNavBarList>
  • toggleCollapsedMenu will toggle from false to true and reversed when the <StyledNavBarBurger> is clicked

This is where the the variable will be toggled with the onClick event.

let collapsedMenuIsActive = false;

const toggleCollapsedMenu = () => {
    collapsedMenuIsActive = (!collapsedMenuIsActive);
}

{/* I have tried both of these two lines below here */}
{/* <StyledNavBarBurger onClick={toggleCollapsedMenu}> */}
<StyledNavBarBurger onClick={() => toggleCollapsedMenu}>
    ...
</StyledNavBarBurger>
<StyledNavBarList isActive={collapsedMenuIsActive}>
    ...
</StyledNavBarList>

This is my styled component.

export const StyledNavBarList = styled.ul`
    ...

    ${MEDIA.smallPhone`
        display: ${props => props.isActive ? 'block' : 'none'};
        ...
    `}
`;

I expect when the onClick event will be fired that the variable that i'm updating will update the the props.isActive value inside my styled component.


Solution

  • If you want to trigger React to re-render based on a variable, you should be using setState and storing your collapsedMenuIsActive in your state object. Something like the following should work, but note without your full code, it may not be exact:

    export default class extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                collapsedMenuIsActive: false
            };
        }
    
        toggleCollapsedMenu = () => {
            // This will update the state in your state object
            // and instruct React to re-render this component with the new state.
            // It's important that you use the function form of setState when
            // changing the state based on current/previous state values.
            this.setState(state => ({
                collapsedMenuIsActive: !state.collapsedMenuIsActive
            }));
        }
    
        render() {
            return (
                <React.Fragment>
                    <StyledNavBarBurger onClick={this.toggleCollapsedMenu}>
                        ...
                    </StyledNavBarBurger>
                    <StyledNavBarList isActive={this.state.collapsedMenuIsActive}>
                        ...
                    </StyledNavBarList>
                </React.Fragment>
            );
        }
    }
    

    To learn more about React state, read the official docs. Note that the React.Fragment is not necessary with the state, it's being used here to simply wrap two components in the render to help with this specific example. It could also simply be a div or wrapped by some other node/element.