2

Many people ask how to disable jquery ajax cache in React, while my question is different. I want it to be cached, or maybe more precisely, save the property I got from the first time call with ajax in browser memory or whatever, then it will not call the REST api again.

Below is my code:

import React from 'react';
import $ from 'jquery';

export default class ActivityIndex extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      activities: [],
    };
  }

  componentDidMount() {
    const source = 'http://api.my.com/activities';
    this.serverRequest = $.get(source, (result) => {
      this.setState({
        activities: result,
      });
    });
  }

  componentWillUnmount() {
    this.serverRequest.abort();
  }

  render() {
    let rows = [];
    this.state.activities.forEach((element) => {
      rows.push(
        <div key={element.act_id}>
          <div>{element.act_id}</div>
          <div>{element.act_title}</div>
        </div>
      );
    });

    return <div>{rows}</div>;
  }
}

Every time I click back to this page, it will call the ajax again. I believe it's because in the componentDidMount method I called the ajax. Maybe I should put it in other place? Or how can I cache the ajax result, so then next time when I enter this page, the ajax will not be called?

0

2 Answers 2

2

Building on the comment regarding local storage. You can build a check for local storage into the process of loading the data, if the check comes up empty then run the ajax request.

componentDidMount() {
    const source = 'http://api.my.com/activities';
    // Check for data you need and either get the data from API
    // or use the data in local storage.
    const data = localStorage.getItem('data');
    if (!data) {
        $.get(source, (result) => {
          this.setState({
            activities: result,
          });
          localStorage.setItem('data', data);
        });
    } else {
        this.setState({
            activities: data,
        });
    }
}

You could break this logic out into its own function, and put it in its own module, or use a different life cycle method. However, this follows your current pattern.

Note that you can use an npm library called localForage if you are storing anything other than a string. Or you can convert the return result to a string to store in localStorage. See here for a recent q&a on this topic.

Sign up to request clarification or add additional context in comments.

Comments

1

According to alexi2's answer, I made some change. Maybe useful for other users. Pay attention to the JSON.stringify and JSON.parse, as localstorage can only store string, cannot directly store object:

import React from 'react';
import $ from 'jquery';

export default class ActivityIndex extends React.Component {
  constructor(props) {
    super(props);

    const data = localStorage.getItem('activityindex');
    if (data) {
      this.state = {
        activities: JSON.parse(data),
      };
    } else {
      this.state = {
        activities: [],
      };
    }
  }

  componentDidMount() {
    const data = localStorage.getItem('activityindex');
    if (!data) {
      const source = 'http://api.my.com/activities';
      this.serverRequest = $.get(source, (result) => {
        this.setState({
          activities: result,
        });
        localStorage.setItem('activityindex', JSON.stringify(result));
      });
    }
  }

  componentWillUnmount() {
    if (this.serverRequest) {
      this.serverRequest.abort();
    }
  }

  render() {
    let rows = [];
    this.state.activities.forEach((element) => {
      rows.push(
        <div key={element.act_id}>
          <div>{element.act_id}</div>
          <div>{element.act_title}</div>
        </div>
      );
    });

    return <div>{rows}</div>;
  }
}

1 Comment

You should version your localstorage items so you could invalidate the data if the structure has changed: localStorage.setItem('v1__activityindex', ...) you later change the version to v2 and remove everything that starts with v1__

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.