Home > Software design >  state not being updated before api call
state not being updated before api call

Time:04-05

I'm building a marketplace where a user get to add his own product to it. I have a form component where the user input details about his product. I have a category and subcategory fields. Once the user chooses a category, the subcategory form gets updated ( by making an api call with the new category) with the list of subcategories related to that category. The problem is the api call is made with the oldest category instead of the the new one.

HERE'S MY CODE

// let's say the initial category is man 
  const [category, setCategory] = useState("men");

  const changeSelectedCategory = (category) => {
    // let's say the user get to choose women category from the picker component listed 
       below

    setCategory(category);
    // the new category is women
  };

  useEffect(() => {

    // making the api call
     getSubCategoriesApi.request({ category: category });
    // logging the api fetched data. i'm sending back the selected category by the user
    // the problem is here. it keeps logging 'men', yet the new category is women
      console.log(getSubCategoriesApi.data());
     
     console.log(category);
    // this logs correctly the new category, which is women. the state has been 
      successfully updated, yet in my api call it wasn't. 
  }, [category]);

<Picker
    items={categories}
    changeSelectedCategory={changeSelectedCategory}
    placeholder="Categorie"
/>

my express code. note that i'm just sending back the category choosen by the user to see if it did get updated correctly.

router.post("/products/getSubCategories", async (req, res) => {
  try {
    res.send(req.body);
    // sends old category, men. Yet the user did choose women and 
       state was updated
  } catch (err) {
    res.status(400).send(err);
  }
});

CodePudding user response:

It doesn't look like changeSelectedCategory is being called unless you are calling it inside the Picker Component which can not be seen.

You should use a promise when waiting for data.

getSubCategoriesApi.request({ category: category })
.then(response => {
    console.log(getSubCategoriesApi.data());
  }).catch(error => {
    console.error(error);
  });  

CodePudding user response:

i Somehow made it work by using axios as api client instead of previously used apisauce.

my api sauce hook

import { useState } from "react";

export default useApi = (apiFunc) => {
  const [data, setData] = useState([]);
  const [error, setError] = useState(false);
  const [loading, setLoading] = useState(false);

  const request = async (...args) => {
    setLoading(true);
    const response = await apiFunc(...args);
    setLoading(false);

    if (!response.ok) return setError(true);

    setError(false);
    setData(response.data);
  };

  return { data, error, loading, request };
};

My api call

import { create } from "apisauce";

const apiClient = create({
  baseURL: "http://192.168.1.42:5000/",
});

const endpoint = "/products";

const getSubCategories = (category) =>
  client.post(`${endpoint}/getSubCategories`, category);

export default {
  getSubCategories,
};
```
Form component ( previous one that didn't work )
```
const getProductsCategoriesApi = useApi(listingsApi.getCategories)
const [category, setCategory] = useState("men");

  const changeSelectedCategory = (category) => {
    // let's say the user get to choose women category from the picker component listed 
       below

    setCategory(category);
    // the new category is women
  };

  const getProductsSubCategoriesApi = useApi(listingsApi.getSubCategories);

  useEffect(() => {

    // making the api call
     getSubCategoriesApi.request({ category: category });
    // logging the api fetched data. i'm sending back the selected category by the user
    // the problem is here. it keeps logging 'men', yet the new category is women
      console.log(getSubCategoriesApi.data());
     
     console.log(category);
    // this logs correctly the new category, which is women. the state has been 
      successfully 
}, [categorySelected]);

the new api call that did work using axios and ditching api hook i created

useEffect(() => {
    axios
      .post("http://localhost:5000/products/test", { name: categorySelected })
      .then(function (response) {
        // successfully logs the new category. 
        console.log(response.data);

      })
      .catch(function (error) {
        // handle error
        console.log(error);
      })
      .then(function () {
        // always executed
      });
  }, [categorySelected]);
  • Related