question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Safe to use setGlobal anywhere?

See original GitHub issue

Hey, really cool library.

I have a quick question though. Is using setGlobal inside components safe? Specifically functional components. I’m using the following pattern for instance:

import React from 'react';
import { setGlobal, useGlobal } from 'reactn';

interface InputProps {
  stateKey: string; // state identifier
  label: string;
}

export default (props: InputProps) => {
  const [value, setValue] = useGlobal(props.stateKey);
  if (value === undefined) {
    setGlobal({ [props.stateKey]: '' });
  }

  return (
    <div>
      <div>{props.label}</div>
      <input
        value={value}
        onChange={e => {
          e.preventDefault();
          setValue(e.target.value);
        }}
      />
    </div>
  );
};


based off of the example code that uses classes and calls setGlobal in componentDidMount.

Finally, I tried calling setGlobal inside of useEffect to no effect hence the need for wrapping setGlobal in an if statement. Is this a bug or intentional?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
CharlesStovercommented, Dec 1, 2018

This took a bit of brainstorming, but the issue is that you cannot subscribe to a property that does not exist. This is because ReactN uses a Proxy polyfill with 100% browser support as opposed to the built-in JavaScript Proxy, which only supports 87% of browsers. One of the trade-offs is that it cannot listen for non-existing property changes. You are accurately grabbing that the value is undefined, but in doing so, your component instance is not registering to be re-rendered when that property changes, because that property does not exist.

There are two solutions to this:

  1. Create the property before rendering this component. If a parent is rendering these components, that parent can set these properties before returning their JSX:
const Parent = () => {
  return stateKeys.map((stateKey) => <Input stateKey={stateKey} />);
};

// can become

const Parent = () => {
  // Modify the global object as a whole,
  //   so that we can mutate multiple keys in one function call.
  const [ global, setGlobal ] = useGlobal();

  // Strip keys that already exist:
  const newKeys = stateKeys.filter(
    stateKey =>
      !Object.prototype.hasOwnProperty.call(global, stateKey)
  );

  // Set keys that don't exist:
  if (newKeys.length > 0) {
    setGlobal(newKeys.reduce(
      (acc, newKey) => ({
        ...acc,
        [newKey]: null
      }),
      Object.create(null)
    ));
    return null;
  }

  // If all keys exist, render an element for each key:
  return stateKeys.map((stateKey) => <Input stateKey={stateKey} />);
  1. I have a use-force-update package that can be used as a React hook to force re-rendering. It works to fix your issue, as shown below:
import { useGlobal } from 'reactn';
import useForceUpdate from 'use-force-update';
import './App.css';

const App = () => {
  const [ value, setValue ] = useGlobal('test');
  const forceUpdate = useForceUpdate();
  if (value === undefined) {
    setValue('hello world');
    forceUpdate();
    return null;
  }
  console.log(value);
  return null;
};

export default App;

I typically do option 1 and instantiate values before accessing them, but as far as code readability codes, the second option appears to read better to me. It’s an entirely opinionated topic. Whichever way makes the most sense to you as a developer and for your app.

EDIT: I might see what I can do to treat this issue as “Calling setValue should forceUpdate when the property does not exist,” and try to include the forceUpdate function call inside the setValue function that is returned by the hook, only for values that are undefined.

1reaction
CharlesStovercommented, Dec 1, 2018

The setGlobal helper function is safe to use, but I’m not sure I’d recommend it. I can’t think of a reason it would ever cause an error to use it like this, but it isn’t the design pattern; it just coincidentally works fine. I can’t guarantee it will always work equivalently in future versions.

This may be closer to what you are looking for:

const [ value, setValue ] = useGlobal(props.stateKey);
if (value === undefined) {
  setValue('');
  return null; // Do not render until a value exists.
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

You Can Definitely Use Global Variables To Manage Global ...
Yes you can use global state anywhere as long as it's in react component. 1 ...
Read more >
Why you shouldn't use global variables in Flutter
Encapsulation makes it safe and easy to maintain code. If you want to use encapsulation effectively, you have to ban global variables.
Read more >
swift - How to create a global variable? - Stack Overflow
You can use this variable in any class or anywhere let string = MyVariables.yourVariable println("Global variable:\(string)") //Changing value of it ...
Read more >
How do I make a variable accessibl… | Apple Developer Forums
A Global Variable doesn't work as it's range is only within the target. ... It depends on what you want to store, how...
Read more >
Global Usings in C# 10 and .NET 6 In 10 Minutes or Less
In C# 10, we have the ability to set global using in our application. See how in this 10-Minute Training video.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found