-1

I'm trying to create an image overlay with no scroll, and I therefore need to style the body when my li is active. I'm trying to do this through Helmet, but it's not working. It just says <body class=""> in the browser—no matter if a li is active or not.

The component:

import React, { useState } from "react"
import { Helmet } from "react-helmet"

export default function ToggleActive({ children, size }) {
  const [isActive, setActive] = useState("false")

  const handleToggle = () => {
    setActive(!isActive)
  }

  return (
    <li className={isActive ? size : "active"} onClick={handleToggle}>
      <Helmet>
        <body className={isActive ? null : "no-scroll"} />
      </Helmet>
      {children}
      <button onClick={handleToggle} />
    </li>
  )
}

What's wrong here?

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67
Magnus Kolstad
  • 407
  • 1
  • 6
  • 17
  • 1
    One thing wrong: !!"false" != false // true – JeanJacquesGourdin Jun 23 '22 at 13:05
  • OK, I guess it says `null` since the `body` isn't active. The question is how do I make it active when the `li` is active? – Magnus Kolstad Jun 23 '22 at 13:08
  • You are saying that you can find a case where li has the class "active" and body the null one ? – JeanJacquesGourdin Jun 23 '22 at 15:08
  • Yes. What am I doing wrong? – Magnus Kolstad Jun 23 '22 at 15:38
  • Can you please tell me what happens when you get rid of the ternary operator and only keep 'active' and 'no-scroll' please ? Are they both in the state you want ? – JeanJacquesGourdin Jun 23 '22 at 15:49
  • Yes, they are. So Helmet is "working" fine when simply declaring a class. – Magnus Kolstad Jun 23 '22 at 15:54
  • 1
    I cannot help further. The only thing that bothers me is the fact that you are not using a boolean, from what I understand ii will not change much if you change "false" to false. But be carefull using this kind of syntax because a string like "false" is true. Also, from what i know it is better to do setActive(isActive => !isActive). Dont know why tho. Good luck have fun =) – JeanJacquesGourdin Jun 23 '22 at 16:06
  • Thanks. I don't get why this isn't working—it must be because of Helmet. Setting the state works for all other elements I've tried. – Magnus Kolstad Jun 24 '22 at 03:43
  • I found a "solution" using `useEffect(() => { document.body.classList.toggle("no-scroll", elementState) }, [elementState])`. But it causes the page to jump up to the top every time the `li` loses its active state. – Magnus Kolstad Jun 24 '22 at 07:29

1 Answers1

0

I don't think this is possible with Helmet.

Anyway, I found a solution:

import React, { useState, useEffect } from "react"

function ToggleActive({ children, size }) {
  const [elementState, setElementState] = useState(false)

  function handleClick() {
    setElementState(!elementState)
  }

  useEffect(() => {
    document.body.classList.toggle("no-scroll", elementState)
  }, [elementState])

  return (
    <li className={elementState ? "active" : size} onClick={handleClick}>
      {children}
      <button onClick={handleClick} />
    </li>
  )
}

export default ToggleActive
Magnus Kolstad
  • 407
  • 1
  • 6
  • 17