7

I am getting username from server and i want to use the same user name from some other component. I know session Storage is one of the way to deal with it but i dont want to use for security reason. How can we create a global object in react?

Rahul
  • 235
  • 2
  • 5
  • 14

5 Answers5

8
// most simplistic
window.myAppData = {
  userName: 'chad123',
  language: 'EN',
  // other stuff
};

window.myAppData.userName // 'chad123'

But most apps require something a bit more complex. You could use React context.

https://reactjs.org/docs/context.html


Context provider

// create context provider and consumer
const UserContext = React.createContext();
export default UserContext;
// wrap part of your app (or whole app) 
// with Provider that needs access to user
class App extends React.Component {
  constructor() {
    super();
    this.state = {
       user: null  
    };
  }

  componentDidMount() {
    yourUserAPI().then(user => this.setState({ user }));
  }

  render() {
    return (
      <UserContext.Provider value={this.state.user}>
        <MyComponent />
      </UserContext.Provider>
    );
  }
}

Context consumer

A) Current standard

// use anywhere in your app like this
// PS! must be descendant of Provider
class MyComponent extends React.Component {
  render() {
    return (
      <UserContext.Consumer>
        {user => {
          // do stuff with 'user'
        }}
      </UserContext.Consumer>
    );
  }
}

B) React Hooks (IN ALPHA)

// only works with functional 
// components (no classes)
function MyComponent() {
  const user = React.useContext(UserContext.Consumer);
  // do stuff with 'user'
  return 'something';
}
Solo
  • 6,687
  • 7
  • 35
  • 67
  • With window object..it makes it a lot simpler but i am trying to access it in different tab due to which i am unable to access. Is there anything you suggest? – Rahul Nov 28 '18 at 03:25
  • Local Storage is pretty much your only option here then. I think new APIs like Service Worker could also help out here (messaging between tabs/windows) but browser support is bad for most app standards. – Solo Nov 28 '18 at 03:54
  • Keep in mind that there shouldn't be any security differences here, if bad actor can access Local Storage, he most likely also knows how to access everything else (ex. secure cookies). – Solo Nov 28 '18 at 03:59
4

I think to achieve that you need to use "React's context API"

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.

// Context lets us pass a value deep into the component tree
// without explicitly threading it through every component.
// Create a context for the current theme (with "light" as the default).
const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    // Use a Provider to pass the current theme to the tree below.
    // Any component can read it, no matter how deep it is.
    // In this example, we're passing "dark" as the current value.
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// A component in the middle doesn't have to
// pass the theme down explicitly anymore.
function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // Assign a contextType to read the current theme context.
  // React will find the closest theme Provider above and use its value.
  // In this example, the current theme is "dark".
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

For further info do visit the link React context api

Community
  • 1
  • 1
Vijay Singh
  • 132
  • 10
2

You need a global state management like Redux.

Once you have this setup you can map your global state to your local component props and access it like you do any other prop: this.props.globalUsername.

I recommend you learn Redux by following their example program on the official website https://redux.js.org/basics/exampletodolist

Shawn Andrews
  • 1,432
  • 11
  • 24
  • Mapping Redux States to Local State is not a good thing in ReactJS, it's just overhead in your application. That's why redux documentations recommend "mapStateToProps" not "mapStateToState". – aprogrammer Nov 28 '18 at 02:06
  • Sorry i mean't global state to props. Updated post – Shawn Andrews Nov 28 '18 at 02:09
1

Well you can create a global variable in ReactJS but it doesn't make it more "secure" over Session/Local storage.

I think creating a global variable in React project is not the best practice at all because of this simply reason: Should components track down this variable for any change ? If the answer is yes, what you are looking at should be "How to manage global state in React" not "How to create a Global Variable in React".

You can achieve it with Redux. As official documentation says "Redux is a predictable state container" but you can think it as Global State Container for your app.

You can check redux out from that url: https://redux.js.org/

aprogrammer
  • 1,764
  • 1
  • 10
  • 20
  • While redux would make sense but all i need is to access username in some other component. Isnt there any easier way to do it? – Rahul Nov 28 '18 at 03:18
1

USE CUSTOM HOOKS

It is very simple

globals.js

let _obj = {}

export const setGlobal = (obj) => {
    Object.assign(_obj, obj)
}
export const getGlobal = varName => {
   if(_obj[varName] !== undefined){
      return _obj[varName]
   }
   else {
      return null
   }
}

component1.jsx

import React.....
import { setGlobal } from "./globals";
import.....

setGlobal({ title : "welcome" })

class comp.... {

   
   render{
      return(){
         <i onClick={()=>setGlobal({location: "House"})}>Cmponent1</i>
      }
   }
}
module exp...

Component2.jsx

import React.....
import { setGlobal, getGlobal } from "./globals";
import.....

setGlobal({ greet : "Hi"})

class comp.... {

   
   render{
      return(){
         <i>{getGlobal("greet")}, {getGlobal("title")} to our {getGlobal("location")}</i>
      }
   }
}
module exp...