0

I saw similar questions in here, but they aren't addressing this specific issue.

I have a react function component like this,

function Overlay() {
  return <div className="off"></div>;
}

I want to change its className property later based on a click event that occurs on a Btn element. Note that the Btn element isn't a parent or a child of the Overlay element.

function Btn() {
  return <button onClick={changeOverlayProperty} ></button>;
}

So, what should "changeOverlayProperty" do to achieve the result? Is there any "react way" to do it other than relying on the usual element methods such as "getElementsByClassName"? Giving actual codes will be helpful as I'm totally new to ReactJS.

Manu Soman
  • 153
  • 11
  • At least related, probably a dupe target: https://stackoverflow.com/questions/57860208/how-to-share-react-context-state-across-separately-mounted-component-trees – T.J. Crowder May 12 '22 at 13:02
  • Use higher order functions – Liam May 12 '22 at 13:04
  • 2
    Did _none_ of the comments [in the question you deleted](https://stackoverflow.com/questions/72214515/how-to-change-react-component-properties-based-on-random-events) help at all? State management, for example? You could use [context](https://www.freecodecamp.org/news/react-context-for-beginners/), or [a state management library](http://shorturl.at/vADI1), or maybe just [lifting state up](https://reactjs.org/docs/lifting-state-up.html) would be sufficient. But these are all personal decisions that you have to make as a developer based on your app structure, and the available tools. – Andy May 12 '22 at 13:06
  • Deleting questions and then re-posting them later is a pretty good way to get [yourself question banned](https://meta.stackoverflow.com/questions/255583/what-can-i-do-when-getting-we-are-no-longer-accepting-questions-answers-from-th). – Liam May 12 '22 at 13:07
  • @Liam I modified the question and re-posted based on the Stackoverflow suggestion itself. – Manu Soman May 12 '22 at 17:02
  • Editing the question is fine. You need need to wait for it to be reopened, IF it meets the criteria. By deleting a closed question, then posting another and then getting that on closed you've put a black mark against your account. Get too many of them and you go in the sin bin – Liam May 13 '22 at 08:29

1 Answers1

1

The ContextAPI can be used to send the className value to another Component:

import { createContext, useState, useContext } from 'react';
const Context = createContext("off"); // <= Create a Context so that state can be shared among different Components (including siblings)

function Overlay() {
  const { className } = useContext(Context); // Grab the className value from the Context. The value className will be set via the Btn Component's click handler
  return <div className={className}>Overlay</div>;
}

function Btn() {
  const { setClassName } = useContext(Context); // Grab the setClassName method from the Context
  return <button onClick={()=> setClassName("on")} >Change Class</button>;
}

export default function App() {
  const [ className, setClassName ] = useState("off");
  return (
    <>
    {/* Wrap the Components that need to share some value in a Context.Provider and share some values via the value prop */}
    <Context.Provider value={{ className, setClassName }}>
      <h1>React</h1>
      <Overlay />
      <Btn />
    </Context.Provider>
    </>
  );
}

<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>
<style>.off { background: red } .on { background: green }</style>
<script type="text/babel">
const Context = React.createContext("off");

function Overlay() {
  const { className } = React.useContext(Context);
  return <div className={className}>Overlay</div>;
}

function Btn() {
  const { setClassName } = React.useContext(Context);
  return <button onClick={()=> setClassName("on")} >Change Class</button>;
}

function App() {
  const [ className, setClassName ] = React.useState("off");
  return (
    <Context.Provider value={{ className, setClassName }}>
      <h1>React</h1>
      <Overlay />
      <Btn />
    </Context.Provider>
  );
}

ReactDOM.render( <App />, document.getElementById("root") );
</script>
Kostas Minaidis
  • 4,681
  • 3
  • 17
  • 25