I have a custom hook written to show or hide a list when a button clicked. Below is the custom hook snippet I have written:
import { useEffect } from "react";
import { useState } from "react";
function useVisibilityStatus() {
const [isVisible, setIsVisible] = useState(true);
useEffect( () => {
setIsVisible(!isVisible);
}, [isVisible]);
return isVisible;
}
export default useVisibilityStatus;
And in another component I have written the logic to view or hide the list.
import ProductListView from "../common/ProductListView";
import SideNavView from "../common/SideNavView";
import SimpleMap from '../googlemap/SimpleMap';
import useVisibilityStatus from '../customhooks/useVisibilityStatus';
function ServiceContentView() {
const listVisible = useVisibilityStatus();
return (
<div className="row p-0 vw-100 service-view-body bg-primary position-relative">
<div className="zindex-value position-absolute">
<div className="service-view-sidenav float-end">
<SideNavView />
</div>
</div>
{listVisible && <ProductListView />}
<SimpleMap />
</div>
);
}
export default ServiceContentView;
And in the SideNavView
I have the button where upon clicking it shows the product list or hides it if it is visible. The SideNavView
is incomplete, as I am bit struggling on how to fit my requirement in ReactJS.
import useVisibilityStatus from '../customhooks/useVisibilityStatus';
function SideNavView() {
const listVisible = useVisibilityStatus();
const handleClick = () => {
}
return (
<div className="">
<div className="row">
<div className="card p-0 w-100 border-radius-none sidenav-view" onClick={handleClick}>
<span className="text-center mt-2 text-white">
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" fill="currentColor" className="bi bi-card-list" viewBox="0 0 16 16">
<path d="M14.5 3a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h13zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13z"/>
<path d="M5 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 5 8zm0-2.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0 5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-1-5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0zM4 8a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0zm0 2.5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0z"/>
</svg>
</span>
<div className="card-body p-0">
<h5 className="card-title text-center text-white">View Products</h5>
</div>
</div>
</div>
</div>
)
}
export default SideNavView;
React hooks don't magically share state, so with the current useVisibilityStatus
implementation they will each have and update their own state independently.
What you can do is create a React Context to hold the single isVisible
state value and expose it and an updater function to consumers.
import { createContext, useContext, useState } from 'react';
const VisibleContext = createContext({
isVisible: false,
toggleIsVisible: () => {},
});
export const useVisibilityStatus = () => useContext(VisibleContext);
const VisibleContextProvider = ({ children }) => {
const [isVisible, setIsVisible] = useState(true);
const toggleIsVisible = () => setIsVisible(isVisible => !isVisible);
return (
<VisibleContext.Provider value={{ isVisible, toggleIsVisible }}>
{children}
</VisibleContext.Provider>
);
};
export default VisibleContextProvider;
The VisibleContextProvider
just needs to wrap the part of the ReactTree that contains the components that need to access its context value, e.g. ServiceContentView
and SideNavView
, and these components use the useVisibilityStatus
to read the current isVisible
state value or access the toggleIsVisible
updater function.
import VisibleContextProvider from '../path/to/VisibleContextProvider';
...
return (
...
<VisibleContextProvider>
...
<ServiceContentView />
...
</VisibleContextProvider>
...
);
import ProductListView from "../common/ProductListView";
import SideNavView from "../common/SideNavView";
import SimpleMap from '../googlemap/SimpleMap';
import { useVisibilityStatus } from '../path/to/VisibleContextProvider';
function ServiceContentView() {
const { isVisible } = useVisibilityStatus();
return (
<div className="row p-0 vw-100 service-view-body bg-primary position-relative">
<div className="zindex-value position-absolute">
<div className="service-view-sidenav float-end">
<SideNavView />
</div>
</div>
{isVisible && <ProductListView />}
<SimpleMap />
</div>
);
}
export default ServiceContentView;
import { useVisibilityStatus } from '../path/to/VisibleContextProvider';
function SideNavView() {
const { toggleIsVisible } = useVisibilityStatus();
const handleClick = () => {
toggleIsVisible();
};
return (
<div className="">
<div className="row">
<div
className="...."
onClick={handleClick}
>
<span className="text-center mt-2 text-white">
...
</svg>
</span>
<div className="card-body p-0">
<h5 className="....">View Products</h5>
</div>
</div>
</div>
</div>
)
}
export default SideNavView;