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);
}