2

I have following React code

Code

What I would like is to when I hover my "E-commerce" picture App component background should change on "E-commerce" picture background.

So respectively and for other pictures.

I will be very grateful if you help me solve this problem.

2 Answers 2

2

Context, according to the React docs, should be used only for truly global state like current user or theme. Using context for components makes them less reusable.

updated code

Your component tree is App -> SolutionBox -> SolutionItem.

You want to "react" to an event in SolutionItem in App but there is SolutionBox inbetween them so you have to thread the event thru SolutionBox to App.

Step 1

Add a prop to SolutionItem called on OnHover, this will be a function call back that any parent component can use to react 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

Add a prop to SolutionBoxItem called on BGChanged, this will again be a function call back that will be called when any solutionitem onhover happens. This function will take a menuName string and pass either the current menu name or default.

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 the changes. In here we now set state when ever the mouse enters or leaves a solution item. From here you have to change the background, you are using css to control the background url, this will be harder since you now need css class for each background type. You could use the bgImage state value to change the name of the extra css className like 'AppSalesMarketing', 'AppEcommerce', etc.

    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

Leave the original App class but based on the bgImage value add an additional one using the name of the bgImage + App like below to cascade down the updated background-image value.

.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

I added lodash to test that the incoming props are functions before I call them, it is good to do defensive programming because you never know who may use your component in the future.

let callBGChanged = menuName => {
    if (_.isFunction(onBGChanged)) {
      onBGChanged(menuName);
    }
  };  
Sign up to request clarification or add additional context in comments.

2 Comments

thank you Frank, I change main background part from css. Can you look this one? codesandbox.io/s/zen-cartwright-9xlmz?file=/src/components/… I try change my code but on hover it was show nothing .
@VardanHambardzumyan see the answer, i updated it to handle the css. The beauty of React is that it lets you do what you want so instead of using imported images you can keep your url functions in css and still make it work. Everybody's situation is different and React is designed to be open enough to handle almost all of them!
0

Two ways to solve the problem. One is passing down a function to update state, the other is to useContext. In this case it makes sense to use context because you are passing down a function through multiple components that do not care about the function.

First thing to do is make the background image dynamic in the div's style and use context:

// Put this outside the component
export const BackgroundContext = React.createContext(null);

// -- snip
const [backgroundImage, setBackgroundImage] = useState(Ecommerce);
const updateBackgroundImage = newImage => setBackgroundImage(newImage);

// -- snip
<BackgroundContext.Provider value={updateBackgroundImage}>
  <div className="App" style={{ backgroundImage: `url(${backgroundImage})` }}>
  {/* -- snip */}
</BackgroundContext.Provider>

Now in your SolutionsSectionBoxItem component you can import the background context:

import BackgroundContext from "../App";

Then using that context and react's mouseover api, update the selected background image:

  const setBackgroundImage = useContext(BackgroundContext);
  // -- snip
  <img onMouseOver={() => setBackgroundImage(solutionIMG)} {/* -- snip -- */} />

You can read more here: https://reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.