0

So in my React app, I'm using fetch API to get list of "thread" items and another call to get list of "categories". My "thread" list gets rendered into DOM right away and in one DOM element it depends on existence of "categories" list. It works most of the time but once in a while "thread" gets fetched before "categories" is populated and DOM element that tries to access the "categories" throws error saying that I'm trying to access a property of an undefined element. I basically need to find a way of waiting for "categories" to fetch and populate before fetching "threads".

useEffect(() => {
  getCategories();
  getThreads();
}, []);

function getThreads() {
loadThreads(categoryId, Feed.threadPage++, 10)
  .then((r) => {
    if (r.status === 200) {
      r.text().then((responseBody) => {
        let responseBodyObject = JSON.parse(responseBody);
        if (responseBodyObject.threads.length === 0)
          setHasMoreThreads(false);
        setThreads(threads.concat(responseBodyObject.threads));
      });
    } else {
      toast.error("Failed to fetch threads");
    }
  })
  .catch((e) => toast.error("Failed to fetch threads."));
}

function getCategories() {
loadCategories()
  .then((r) => {
    if (r.status === 200) {
      r.text().then((responseBody) => {
        let responseBodyObject = JSON.parse(responseBody);
        setCategories(responseBodyObject.categories);
      });
    } else {
      toast.error("Failed to load the categories");
    }
  })
  .catch((e) => toast.error("Failed to load the categories"));
}

And in my DOM I've got:

{threads.map((v, i) => (
            <div key={i}>
              <div
                className={classes.feedThreadBox}
                onClick={(e) => console.log(v)}
              >
                <h5 style={{ marginBottom: 0 }}>
                  {v != undefined && v.title}
                </h5>
                <i
                  className="fa fa-circle fa-xs"
                  style={{
                    color:
                      "#" +
                      categories.find(
                        (category) => category.id === v.categoryId
                      ).color,
                    fontSize: 10,
                  }}
                ></i>{" "}
                {
                  categories.find(
                    (category) => category.id === v.categoryId
                  ).name
                }
              </div>
              <hr></hr>
            </div>
          ))}

How do I go about making sure that "categories" is populated before "threads.map" renders?

1
  • You can use async/await in your case. Commented Apr 29, 2020 at 9:09

1 Answer 1

1

You should use async/await:

  • put the async keyword in front of your getCategories() function

  • use await in the function's body

You can find more info of the usage here

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

Comments

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.