props and context are the ways that react has for moving data between components. Built into these are the fact that if you rerender the source component and it has a new value for the prop/context, then the destination component will rerender too. The child component does not need to somehow register an event listener on the props/context, and then set state when the value changes; it's enough that the props/context changed.
If you do a global variable, then yes, it can in principle be available to all components. However, you will need to write code which listens to changes in that global variable (for example, with an event emitter or an observable), and then every component that consumes it will need to set local state when the global value changes, in order to rerender itself.
context only transmits data to wrapped components, while global variables have no such restriction
While you describe this as a restriction, it's sometimes a very useful benefit.
For example, suppose you are making a group of components that need to work together, such as a TabContainer and a TabPanel. They need to share data between themselves. Since context is only available to the wrapped components, the TabContainer can render a context provider, and the TabPanels can access that context. And if there are multiple TabContainers on the page, they won't interfere with eachother.
Or as another example, suppose you have a Theme object that sets the colors for your app. It's provided via context, and your ui components use it to style themselves. But you also want to let the user change the theme, and see a preview of the change. Since the Theme is using context, you can create a new context provider that just wraps around the preview part of your app. Components inside the preview will use the modified theme, while the rest of the app behaves as normal.
In short: you can put your context provider at whatever level makes sense for your needs. If you want it to be global, put it at the top of your component tree and it's global. But if you want something confined to a region, you can do that too. A global variable does not have this flexibility.
Answer from Nicholas Tower on Stack OverflowI feel like use context can go pretty much everthing but zustand makes it even more easier .
reactjs - How to declare a global variable in React? - Stack Overflow
Is there anything wrong with using global variables?
reactjs - Using context to store variable globally React.js - Stack Overflow
Correctly create global variables in React
Videos
Beyond React
You might not be aware that an import is global already. If you export an object (singleton) it is then globally accessible as an import statement and it can also be modified globally.
If you want to initialize something globally but ensure its only modified once, you can use this singleton approach that initially has modifiable properties but then you can use Object.freeze after its first use to ensure its immutable in your init scenario.
const myInitObject = {}
export default myInitObject
then in your init method referencing it:
import myInitObject from './myInitObject'
myInitObject.someProp = 'i am about to get cold'
Object.freeze(myInitObject)
The myInitObject will still be global as it can be referenced anywhere as an import but will remain frozen and throw if anyone attempts to modify it.
Example of react state using singleton
https://codesandbox.io/s/adoring-architecture-ru3vt (see UserContext.tsx)
If using react-create-app
(what I was looking for actually) In this scenario you can also initialize global objects cleanly when referencing environment variables.
Creating a .env file at the root of your project with prefixed REACT_APP_ variables inside does quite nicely. You can reference within your JS and JSX process.env.REACT_APP_SOME_VAR as you need AND it's immutable by design.
This avoids having to set window.myVar = %REACT_APP_MY_VAR% in HTML.
See more useful details about this from Facebook directly:
https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables
Why don't you try using Context?
You can declare a global context variable in any of the parent components and this variable will be accessible across the component tree by this.context.varname. You only have to specify childContextTypes and getChildContext in the parent component and thereafter you can use/modify this from any component by just specifying contextTypes in the child component.
However, please take a note of this as mentioned in docs:
Just as global variables are best avoided when writing clear code, you should avoid using context in most cases. In particular, think twice before using it to "save typing" and using it instead of passing explicit props.
Hey, I'm pretty experienced with programming but somewhat new to React. I'm working on an application which is simple enough in terms of data that integrating Redux would be kind of unnecessary (and would require me to learn how to use the library lol).
There is a very small amount of global data related to the URL, params, and current route/router data that I would like to share with all children of the "app layout" (main content) component. The app layout is the direct child of the router so it has all of the router's info passed to it as props.
I'm thinking about just putting this data in an object on the "window" object from within the constructor of the app layout component, then just accessing it as such from children components. Could this lead to anything bad or is it considered bad practice?
As far as I can tell, my only other option is using the context API. Would that be the better option? Are there any other good options? I'm mostly aiming for simple.
Your use case here will be consumed by something outside of React (an Apollo Link), so Context does not make any sense here - Context would make a value available to children in the React tree, but your link is not a child in a React Tree.
Instead you can just export an object and modify that object (you probably cannot reassign it depending on how you import/export it, but you can always modify it).
// index.js
export const globalData = {
auth: null
}
// anywhere else
import { globalData } from './index.js'
globalData.auth = "foo"
That said, you can only work with global data like this if you are not using SSR. If you are using SSR (e.g. in a Client Component in Next.js), you'd need to find another way of doing that.
In that case, you could use Apollo CLient's defaultContext.
if u want to store a variable globally u can use context api or redux-tool kit here i am giving a rough idea how u can achieve this using context API first Create A folder usually context.. inside this create a file usually name as DataProvider.jsx and do thing like this
import { createContext, useState } from 'react';
export const DataContext = createContext(null);
const DataProvider = ({ children }) => {
const [Client, setClient] = useState([]);
return (
<DataContext.Provider value={{
Client, setClient
}}
>
{children}
</DataContext.Provider>
)
}
export default DataProvider;
next step u should wrap your app.js like this
import DataProvider from './context/DataProvider';
function App() {
return (
<DataProvider>
<Home />
</DataProvider>
);
}
export default App;
now u can setclient or u can use client data like below
assume u have a file name Client.jsx where u want to set the client data
const { setCleint} = useContext(DataContext)
set the Client data to setClient just as normal state now in similar way u can render the client list anywhere like this
const { Cleint} = useContext(DataContext);
You can do that by storing the variable in window variable
first store the value of your variable in A.js like this
window.pie = 3.1416;
And you can see the variable value in your Clsb.js component like
console.log(window.pie);
As phuzi said in the comment to your question, declaring global variables in react is a bad idea, in this case the ideal would be to use redux, or else the context api (context hook) so you can access and make the variable available throughout your system.
Link to docs https://reactjs.org/docs/context.html
context with functional component
let's create a context like hook
/src/context.js
import React, { createContext, useState, useContext} from "react";
const UserContext = createContext();
export default function UserProvider({ children }) {
//your variables
//example
const [person, setPerson] = useState('John');
return (
<UserContext.Provider
value={{
person //variables to export
}}
>
{children}
</UserContext.Provider>
);
}
export function useUser() {
const context = useContext(UserContext);
if (!context) throw new Error("useUser must be used within a CountProvider");
const { person } = context;
return { person };
}
after creating the context, around your app you need to place the provider
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import UserProvider from "./src/context.js";
ReactDOM.render(
<UserProvider>
<React.StrictMode>
<App />
</React.StrictMode>
</UserProvider>,
document.getElementById("root")
);
after you already have the provider you can access any file
src/page.js
import React from "react";
import { useUser } from "./context.js";
const Page = (props) => {
const { getPerson } = useUser(); //variable available by context
return (<h1>Test h1</h1>)
};
export default Page ;
obs: i didn't test the code
We are implementing a user system in our react project using amplify and react context to set the global state of the application to the users information. Since I am relatively new to react and am now taking over this project, I am curious if this is the best practice. When sending an API call, I utilize the "useEffect" hook to grab the users attributes then use it as a parameter for the API call.
We have no senior developer at the moment so some direction would go a long way.