6
  • I am trying to build a react app where I can see notifications similar to stackoverflow.
  • when I open two different tabs and open stackoverflow. I see notifications in two different tabs.
  • but when I click that notification icon the numbers diappear.
  • similarly in another tab also number disaapears without refreshing the page.
  • I analysed the stackoverflow site by open in ie and chrome
  • when I click reputation in chrome browser I see a network call happening and in IE browser without refreshing the numbers diappear.
  • I see some values in local storage and session storage.
  • is it possible to achive withot making api calls, for time being can we achieve using mock data
  • I build the tab ui and redirect to the tab page
  • so I google and found this link browser sessionStorage. share between tabs?
  • used it in my react code, for some reason local storage is not setting up
  • its going into this method anotherPage
  • but storage key value is not adding.
  • debugged by putting consoles, but its not printing anything inside window events.
  • can you tell me how to fix it show that I can share the session between different links and tabs.
  • providing my screenhot code snippet and sandbox below

repuation notifications scenario enter image description here message notifications scenario enter image description here

https://codesandbox.io/s/material-demo-j5ec5

demo.js

  anotherPage = () => {
    console.log("redictToStepper --->");
    this.props.history.push("/anotherPage");

    if (!event) {
      console.log("window --->");
      event = window.event;
    } // ie suq
    if (!event.newValue) return; // do nothing if no value to work with
    if (event.key == "getSessionStorage") {
      console.log("window --->");
      // another tab asked for the sessionStorage -> send it
      localStorage.setItem("sessionStorage", JSON.stringify(sessionStorage));
      // the other tab should now have it, so we're done with it.
      localStorage.removeItem("sessionStorage"); // <- could do short timeout as well.
    } else if (event.key == "sessionStorage" && !sessionStorage.length) {
      // another tab sent data <- get it
      var data = JSON.parse(event.newValue);
      for (var key in data) {
        sessionStorage.setItem(key, data[key]);
      }
    }

    //listen for changes to localStorage
    if (window.addEventListener) {
      console.log("window --->");
      window.addEventListener("storage", "xxx", false);
    } else {
      console.log("window --->");
      window.attachEvent("onstorage", "xxx");
    }

    // Ask other tabs for session storage (this is ONLY to trigger event)
    if (!sessionStorage.length) {
      localStorage.setItem("getSessionStorage", "foobar");
      localStorage.removeItem("getSessionStorage", "foobar");
    }
  };

pageOne.js

 render() {
    const {
      showSearchResults,
      searchText,
      typeAhead,
      typeAheadMode,
      canEdit,
      value
    } = this.state;

    const { classes } = this.props;

    return (
      <div className={classes.root}>
        <AppBar position="static" color="default">
          <Tabs
            value={value}
            onChange={this.handleChange}
            indicatorColor="primary"
            textColor="primary"
            variant="scrollable"
            scrollButtons="auto"
          >
            <Tab label="Radiobutton One" />
            <Tab label="checkbox Two" />
          </Tabs>
        </AppBar>
        {value === 0 && <TabContainer>Notification One</TabContainer>}
        {value === 1 && <TabContainer>Notification Two</TabContainer>}
      </div>
    );
  }
  • I kind of made some changes to get local and session storage in https://codesandbox.io/s/material-demo-6ikw1. You should pass the event and the type of storage you want to do in the parameter of the click. – Ganesh chaitanya May 31 '19 at 15:12
  • can you give comments to your code changes since if I see in session storage and local storage I dont see the values getting added –  May 31 '19 at 15:23
  • Please check now. I'm able to see the session storage in the logs. – Ganesh chaitanya May 31 '19 at 15:29
  • @Ganeshchaitanya hey but each time when I submit I need to update the notifications in that tab component, similar to stackoverflow notifications like they close the browser and can see the notifications again. Provided screenshots in my question –  May 31 '19 at 18:22
  • 1
    Have you tried using websockets for this ? – Ewomazino Ukah Jun 08 '19 at 21:58
  • @MazinoSUkah Hey I googled but not able to find any sample example...can you provide links of sample example so that I will build it from scratch –  Jun 10 '19 at 02:37

1 Answers1

4

I had trouble figuring what your codepen and the anotherPage function was trying to achieve, so I am providing you this codepen. Open it in two different windows and look at the shared number of notifications.

Please note that the suggested Local Storage solution is working only on the same browser as browsers does not share their Local Storages.

Here how to synchronize your Local Storage between two windows, without making any remote API call:

First let add an Event Listener. The first argument is the event type (here we are listening to storage), the second one is the callback. Note that listening to storage event works only between two windows (updating storage from a window will not trigger its own listener):

  componentDidMount() {
    window.addEventListener("storage", this.handleStorageUpdate);
  }

Remember to remove this listener when you are not using it anymore (potentially on componentWillUnmount) to prevent any bloat.

  componentWillUnmount() {
    window.removeEventListener("storage", this.handleStorageUpdate);
  }

Now let's take a look at our listener. It will receive all storage changes, but we only want to listen to the notifications changes. When the notifications changes in the storage, we want to update our component state to trigger a rerender with the new value:

  handleStorageUpdate = storageChange => {
    if (storageChange.key === "notifications") {
      this.setState(() => ({ notifications: Number(storageChange.newValue) }));
    }
  };

So now, we are able to have two windows listening to the changes made by each others.

Let's just give a way to increase the amount of notification:

 handleIncreaseNotification = () => {
    const notifications = this.state.notifications + 1;

    localStorage.setItem("notifications", notifications);

    this.setState(() => ({ notifications }));
  };

When increasing the number of notifications, you are setting the Local Storage item to be consumed by the other window. As you are not listening to your own changes of Local Storage, you need to set your state to this new number of notifications.

As you want to see the notification count directly when opening the window, remember to get the value of your Local Storage at one of the earliest state of your component lifecycle:

  constructor(props) {
    super(props);

    const notifications = localStorage.getItem("notifications") || 0;
    this.state = { notifications: Number(notifications) };
  }

Finally you can render the entire component:

  render() {
    const { notifications } = this.state;
    return (
      <div>
        <div> I have {notifications} notifications</div>
        <button onClick={this.handleIncreaseNotification}>increase</button>
      </div>
    );
  }
Namoz
  • 540
  • 2
  • 14
  • Hey using mock data...can you make it to work for different browsers...later using the Mock data I will build the api –  Jun 05 '19 at 22:01
  • 2
    @zizi Local Storage is not shared between browsers, you cannot use mock data to get this working as desired, an API is necessary if you need the notification state to persist across browsers. – Jake Holzinger Jun 11 '19 at 18:43
  • @JakeHolzinger yeah for taht API can you give me a mock dta, so that I will build an api using that and now I will test it with mock dta now...so that I can do a poc with mock data –  Jun 11 '19 at 18:55