dcp3450
dcp3450

Reputation: 11187

Updating a variable after ajax call in ReactJS?

I have a method that gets page data from an api when the user changes the state (using react-route-dom for this). A few pages have attributes that requires a second ajax call to get more data. The problem I'm having is the variable isn't updating with the secondary information. I understand "why" but not how to resolve it.

//page data gets pulled into a state and passed to a child component "page.js"

//gets archive attribute
var isArchive = customMeta.isArchive;
//gets the archive target name
var archiveName = customMeta.archiveName;
//sets the initial value (mostly for debugging)
var worksArchive = "hello world";

//checks if value exists and that it is an archive
if(isArchive && isArchive == "true"){

    //only get the archive info if the name is also present
    if(customMeta.archiveName) {

        //make the ajax call to get the data for the archive pages
        axios.get('http://admin.datasite.co/v2/'+archiveName)
        .then((response) => {
            var archivePages = response.data;

            //if the archive is "works" then create a list of archive pages
            if(archiveName == "works"){

                //run a loop for each page returning a link that passes through a history router
                worksArchive = archivePages.map(function(work){


                    return <Link key={work.id} className="work-item" to="/" ><img src={work.post_meta.targetimg} /></Link>;

                    });

            }
        })
        .catch((error) => {
            console.log(error);
        });
    }
}

...

{worksArchive} //this always outputs "hello world"
...

I've console.loged through the ajax and the map and everything is correct with no errors. I know the issue is the value gets set again after the dom is painted so that's why I don't see the change. I think they way is to save this as a state but not sure how to resolve the problem.

Upvotes: 1

Views: 1291

Answers (2)

Win
Win

Reputation: 5584

Work with state. Store archivePages as an empty Array and and render it, and then once you set the state the component will re-render because the state was updated. Here's an example of how you'll want to handle it below.

class TestComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      archivePage: []
    };
  }
  componentDidMount() {

    //gets archive attribute
    var isArchive = customMeta.isArchive;
    //gets the archive target name
    var archiveName = customMeta.archiveName;
    //sets the initial value (mostly for debugging)
    var worksArchive = "hello world";

    //checks if value exists and that it is an archive
    if (isArchive && isArchive == "true") {
      //only get the archive info if the name is also present
      if (customMeta.archiveName) {
        //make the ajax call to get the data for the archive pages
        axios.get("http://admin.datasite.co/v2/" + archiveName)
          .then(response => {
            var archivePages = response.data;

            //if the archive is "works" then create a list of archive pages
            if (archiveName == "works") {
              //run a loop for each page returning a link that passes through a history router
              this.setState({
                  archivePages: archivePages
              })
            }
          })
          .catch(error => {
            console.log(error);
          });
      }
    }

  }
  render() {
    return (
      <div>
        {this.state.archivePages.map(work => {
          return (
            <Link key={work.id} className="work-item" to="/">
              <img src={work.post_meta.targetimg} />
            </Link>
          );
        })}
      </div>
    );
  }
}

Upvotes: 0

Andrii Starusiev
Andrii Starusiev

Reputation: 7764

Keep your worksArchive in state of component and update it with setState.

class MyComponent extends React.Component{
    constructor(){
        super();
        this.state = {
            worksArchive: "hello world" //initial value
        }
    }
    ...
    //in axios then
        var newWorksArchive = archivePages.map(function(work){
            return <Link key={work.id} className="work-item" to="/" ><img src={work.post_meta.targetimg} /></Link>;
        });
        this.setState({worksArchive: newWorksArchive});
    ...
}

Upvotes: 1

Related Questions