Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
227 views
in Technique[技术] by (71.8m points)

javascript - react app local storage is not setting up

  • 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>
    );
  }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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>
    );
  }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.8k users

...