Search code examples
reactjsjsxuse-effect

How to to trigger useEffects on windows.variable Global Variable change


I am loading the two files and i have a variable called routes that i want to have changed base on a click from another component. I have a global variable called window.showhide thats boolen and another one window.route which is an object array. i want to toggle window.showhide from another component and have useEffect trigger. using window.showhide useEffects does not trigger. i just want to change window.route to route2 from another component. please help me figure this out.

import route1 from "./routes1"
import route2 from ".routes2"
window.showhide = false
window.route = route1
const routes = window.route

export default function App() {
  useEffect(() => {
     if(window.showhide){
         routes = route2
     } else {
         routes = route1
    }
  }, [window.showhide]);
}

Solution

  • useEffect does not have the ability to listen for variables to change, and then cause a rerender of your component. Rather, your component has to already be rerendering due to something else, and then the dependency array decides whether or not to run the extra code found in the useEffect.

    If you want to render a component in react, you need to set state. So the typical solution for your kind of problem is to have a state variable in App, and then pass down a function that lets a child set that state.

    export default function App() {
      const [routes, setRoutes] = useState(route1);
    
      const showHide = useCallback((value) => {
        setRoutes(value ? route1 : route2);
      }, []);
    
      return (
        <ChildComponent showHide={showHide} />
      );
    }
    
    // In the child:
    function ChildComponent({ showHide }) {
      return <div onClick={() => showHide(true)} />
    }
    

    If the components are very far removed from eachother, then passing down via props may be a pain, in which case you can use context instead:

    const ShowHideContext = createContext(() => {});
    
    export default function App() {
      const [routes, setRoutes] = useState(route1);
    
      const showHide = useCallback((value) => {
        setRoutes(value ? route1 : route2);
      }, []);
    
      return (
        <ShowHideContext.Provider value={showHide}>
          <ChildComponent />
        </ShowHideContext.Provider>
      );
    }
    
    // Elsewhere:
    
    function Example () {
      const showHide = useContext(ShowHideContext);
    
      return <button onClick={() => showHide(true)} />
    }