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;
3
Answers
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.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
andSideNavView
, and these components use theuseVisibilityStatus
to read the currentisVisible
state value or access thetoggleIsVisible
updater function.You don’t need to use custom hooks for that task. The better solution is to save visibility status into Main component’s container and pass it as props to child components.
To share state between deeply nested component you can use
context
VisibilityContext.jsx
useVisibilityStatus.js
You need to wrap the
SideNavView
andServiceContentView
withVisibilityContextProvider
SideNavView
andServiceContentView
ParentServiceContentView.jsx
SideNavView.jsx