Home > Back-end >  How to filter an object state variable in React.js?
How to filter an object state variable in React.js?

Time:11-12

I have a state variable stock_data having an array of details of all stock. Structure:

    {
        "scrip_code": 506235,
        "short_name": "ALEMBICLTD",
        "Ex_date": "12 Sep 2022",
        "Purpose": "Dividend - Rs. - 1.8000",
        "RD_Date": "13 Sep 2022",
        "BCRD_FROM": "",
        "BCRD_TO": "",
        "ND_START_DATE": "06 Sep 2022",
        "ND_END_DATE": "12 Sep 2022",
        "payment_date": "",
        "exdate": "20220912",
        "long_name": "ALEMBIC LTD."
    },

I want to filter that data out. I need to add some new key value pairs too (div_or_share and div_amount).

My approach was to make a new array variable myNewData and mapping from state variable stock_data:

  const [stock_data, setStockData] = useState([]);

  var myNewData = [];

  const makeMyNewData = () => {

    console.log("in makeMyNewData with stock_data:", stock_data);

    stock_data.map((item) => {
      var [first, rest, end] = item.Purpose.split("-");
      var newObject = {
        short_name: item.short_name,
        long_name: item.long_name,
        div_or_share: first,
        Ex_date: item.Ex_date,
        div_amount: isNaN(Number(end))
          ? "-"
          : "Rs. "   Number(end).toFixed(2)
      };
      console.log("newObject:", newObject);
      myNewData.push(newObject);
    });
  }

  const fetch_BSE_Data = () => {
    console.log("fetching data");
    return fetch(
      "https://api.bseindia.com/BseIndiaAPI/api/DefaultData/w?Fdate=20220912&Purposecode=P9&TDate=20221216&ddlcategorys=E&ddlindustrys=&scripcode=&segment=0&strSearch=S"
    )
      .then((response) => response.json())
      .then((data) => setStockData(data))
  };

I am fetching the data and storing in stock_data variable using fetch_BSE_Data(), but the console.log below shows that it's empty. So, while calling makeMyNewData(), stock_data is empty:

  useEffect(() => {
    fetch_BSE_Data()
    console.log("after fetching stock_data:", stock_data);
    makeMyNewData();
    setStockData(myNewData);
  }, []);

I want to send this updated stock_data to a child component:

 <DividendCalendar stock_data={stock_data} />

How to resolve this?

Also, the props.stock_data has the original unfiltered data when logged in console, but when I try to initialize a state variable in DividendCalendar, the div_cal_data also turns out to be empty by the console log below:

In DividendCalendar component:

  var [div_cal_data, setDivCalData] = useState(props.stock_data);
  console.log("div_cal_data", div_cal_data);

Can someone help me with this?

CodePudding user response:

Few pointer that could help

move the function inside useEffect

 useEffect(() => {

     const fetch_BSE_Data = async () => {
           console.log("fetching data");
           return await fetch(
                 "https://api.bseindia.com/BseIndiaAPI/api/DefaultData/w?Fdate=20220912&Purposecode=P9&TDate=20221216&ddlcategorys=E&ddlindustrys=&scripcode=&segment=0&strSearch=S"
           )
           .then((response) => response.json())
          // .then((data) => setStockData(data))
       };

     const async fetchData async () =>  {
       const response = await fetch_BSE_Data()
       const mappedItems = makeMyNewData(response);
       // this will replace the data,
       setStockData(mappedItems);
       // if you need to update/add to existing items then use map again
       setStockData(existing => {
          // logic to update existing items and insert new ones
          // [check React js new docs][1] 
       });
     }

     fetchData();
  
   }, []);

check React js new docs to update, insert items in array

// change the makeData

const makeMyNewData = (stock_data) => {

// console.log("in makeMyNewData with stock_data:", stock_data);

const mappedData = stock_data?.map((item) => {
  var [first, rest, end] = item.Purpose.split("-");
  
   const newObject = {
     ...item,
      div_amount: isNaN(Number(end))
        ? "-"
         : "Rs. "   Number(end).toFixed(2)
   }

   return newObject;
 
});

return mappedData
}

Hope it helps

CodePudding user response:

Your fetch_BSE_Data is making an asynchronous call to fetch data, but you're trying to log the data right after it synchronously. If you want to make this work, you can return a promise instead from your function and then await it in your useEffect hook like so:

const fetch_BSE_Data = async () => {
    console.log("fetching data");
    const response = await fetch(url);
    const data = await response.json();
    setStockData(data);
    return data;
};

But another problem you'd face by trying to log the state right after the setState is that you'll only see the data after a re-render. i.e. When the component first renders, your stock_data variable is set to an empty array. When you fetch from the api and set the state, it will trigger a re-render of the component and will populate your state variable. But before this happens, your useEffect fn from the first render will complete execution. During this time, since it's still the first render, the stock_data variable will still be an empty array. If you want to view what the data, just return it from your fetch function and console log it like this:

useEffect(() => {
    const run = async () => {  // We can't use an async function as a callback to useEffect, so we define another fn inside the callback.
      const data = await fetch_BSE_Data();
      console.log("after fetching stock_data:", data);
      makeMyNewData();
      setStockData(myNewData);
   }
   run();
}, []);

If you want to see the value of stock_data on every render, just console log it in the function body right after you define it like this:

const [stock_data, setStockData] = useState([]);
console.log(stock_data); // Should log [] first render, and after the API fetches data, should show you data [...]

To filter your data out, you can do this


const makeMyNewData = () => {

    console.log("in makeMyNewData with stock_data:", stock_data);

    const updated_stock_data = stock_data.map((item) => {
      const [first, rest, end] = item.Purpose.split("-");
      const newObject = {
        short_name: item.short_name,
        long_name: item.long_name,
        div_or_share: first,
        Ex_date: item.Ex_date,
        div_amount: isNaN(Number(end))
          ? "-"
          : "Rs. "   Number(end).toFixed(2)
      };
      return newObject;
    }); // Map function returns a new array 

    setStockData(updated_stock_data);
}

  • Related