According to the React documentation, it is advised to use context only for global state such as the current user or theme. Utilizing context for components can reduce their reusability.
For reference: updated code
The component tree structure is as follows: App -> SolutionBox -> SolutionItem.
When you need to "react" to an event in SolutionItem from App but SolutionBox is in between, you will have to pass the event through SolutionBox to reach App.
Step 1
Add a prop to SolutionItem named onHover, which will be a callback function allowing any parent component to respond to changes.
function SolutionsSectionBoxItem({ solutionIMG, onHover }) {
let callOnHover = state => {
if (_.isFunction(onHover)) {
onHover(state);
}
};
return (
<div className="solutions-section-item-box">
<img
src={solutionIMG}
alt=""
onMouseEnter={() => {
callOnHover(true);
}}
onMouseLeave={() => {
callOnHover(false);
}}
className="solutions-section-item-img"
/>
</div>
);
}
Step 2
Introduce a prop to SolutionBoxItem called onBGChanged, which again will be a callback function triggered upon any SolutionItem hover event. This function will accept a menuName string and pass the current or default menu name.
function SolutionsSectionBox({ onBGChanged }) {
let callBGChanged = menuName => {
if (_.isFunction(onBGChanged)) {
onBGChanged(menuName);
}
};
return (
<div className="solutions-section-box-box">
<SolutionItem
solutionIMG={Ecommerce}
onHover={state => {
callBGChanged(state === true ? "Ecommerce" : "default");
}}
/>
<SolutionItem
solutionIMG={SalesMarketing}
onHover={state => {
callBGChanged(state === true ? "SalesMarketing" : "default");
}}
/>
<SolutionItem
solutionIMG={Analytics}
onHover={state => {
callBGChanged(state === true ? "Analytics" : "default");
}}
/>
<SolutionItem
solutionIMG={Middleware}
onHover={state => {
callBGChanged(state === true ? "Middleware" : "default");
}}
/>
</div>
);
}
Step 3
In the App component, listen for changes. Here, update the state whenever the mouse enters or leaves a solution item. To change the background, CSS is used to control the background URL. This might be challenging as different CSS classes would be required for each background type based on the bgImage state value.
export default function App() {
const [bgImage, setbgImage] = useState(E);
const onBGChanged = menuName => {
setbgImage(menuName);
};
return (
<div className={`App ${bgImage === "default" ? "" : `App${bgImage}`}`}>
<SolutionBox onBGChanged={onBGChanged} />
</div>
);
}
In CSS
Maintain the original App class and add an additional one based on the bgImage value, like 'AppEcommerce', 'AppSalesMarketing', etc., to update the background-image accordingly.
.AppEcommerce {
background-image: url(https://placekitten.com/600/600);
}
.AppSalesMarketing {
background-image: url(https://placekitten.com/500/800);
}
.AppAnalytics {
background-image: url(https://placekitten.com/800/500);
}
.AppMiddleware {
background-image: url(https://placekitten.com/700/700);
}
Extra
To ensure the incoming props are functions before calling them, lodash is added as a defensive measure. This practice is recommended for future-proofing the component.
let callBGChanged = menuName => {
if (_.isFunction(onBGChanged)) {
onBGChanged(menuName);
}
};