Zustand setState outside of component doesn't update - javascript

My store is set inside store.js as all the other Zustand stores:
const retryStore = create(set => ({
retry_n: 0,
setGRetry: (retry_n) => set(state => ({
...state,
retry_n,
})),
}));
export { retryStore };
inside my #/utils/get.js file I try to update the number by 1, using setState as:
const retry_n = retryStore.getState().retry_n
const xxx = xxxStore.getState().xxx
const xxxx = xxxxStore.getState().xxxx
var j=0;
const maxretry = 20;
const myFetch = async () => {
try {
let url = `...`
while(j < maxretry){
console.log('while try n:',j) // 1,2,3... ecc
console.log('get.js retry_n:',retry_n) // always 0
if (isItRetry){ // TRUE
retryStore.setState({ retry_n: retry_n + 1})
console.log('playThis retry_n now:',retry_n) // always 0
}else{
...
}
if (a != b){ ... return }
j++
}
etc...
shouldn't this increment by 1 each loop? why is always 0? I use other stores the same way in the same file and all work but this one.

Related

React Component rewrites parent's state

i'm pretty new at React so i need some help
i have an component which has structure smth like that
class App extends React.Component{
constructor(props) {
super(props);
this.state = {
...
portfolio: []
...
}
...
this.userDataUpdatesSubscribe = this.userDataUpdatesSubscribe.bind(this);
this.dealComplete = this.dealComplete.bind(this);
...
}
async componentDidMount() {
...
await this.userDataUpdatesSubscribe();
...
}
userDataUpdatesSubscribe(){
//fs here is a Firebase Firestore SDK
//firebase.initializeApp(firebaseConfig);
//const fs = firebase.firestore();
fs.collection('users').doc(...).onSnapshot(
e => {
this.portfolioInit(e.data().portfolio).then(v =>
this.setState({
portfolio: v,
...
})
);
}
);
}
async portfolioInit(stocks){
let a = [];
for (const v of stocks) {
let i;
await this.getPrice(v.ticker).then(e => {
i = e.trade.p
});
a.push({
ticker: v.ticker,
name: StocksData[v.ticker].name,
price: await i,
avgPrice: v.avgPrice,
count: v.count
});
}
return a;
}
async getPrice(ticker, date=null){
let a;
let u = ...;
await fetch(
u,
{
...
}
).catch(() => {...}).then(
async e => {
a = await e.json();
}
)
return await Promise.resolve(a);
}
render(){
<...>
<TheProblemComponent p={this.state.portfolio} .../>
</...>
}
}
so i have a component where state updates on firestore snapshot. i don't store prices in database but i need it so i use getPrice method which returns me price. when i've got all prices the state updates. then i convey data to which has structure like
const TheProblemComponent = (p) => {
const makeDeal() => {
let x = p.p;
...
some calculations
...
for(let i = 0; i < x.lenght; i++){
x[i] = {
ticker: x[i].ticker,
avgPrice: x[i].avgPrice,
count: x[i].count
} // so here i just delete price and name properties which are from props
}
fs.collection('users').doc(...).update({portfolio: x, ...}).then(() => {
...some actions
})
}
return <Button
onClick={() => {console.log(p.p); makeDeal()}}
></Button>
}
so again. i have a parent component which state updates on firestore snapshot. portfolio in database has avgPrice, count and ticker. in my component it also has price which i receive from the getPrice method and name which is constant. this state portfolio i send to ProblemComponent as props which should not modify the parent's state but it does. console.log() prints array without price and name even when executes before makeDeal function. i've tried to store price and name in DB but i want not to do it
It appears you are mutating the parent state via the passed prop because you are mutating the p prop.
const makeDeal() => {
let x = p.p; // <-- saved reference to p.p (portfolio??)
...
some calculations
...
for(let i = 0; i < x.lenght; i++){
x[i] = { // <-- mutation!!
ticker: x[i].ticker,
avgPrice: x[i].avgPrice,
count: x[i].count
}
}
fs.collection('users')
.doc(...)
.update({ portfolio: x, ... })
.then(() => {
...some actions
});
}
To resolve, shallow copy the data you want to update. I suggest also using more descriptive variable names so the code is more readable.
const makeDeal() => {
const portfolio = [...p.p]; // <-- copy array into new array reference
...
some calculations
...
for(let i = 0; i < portfolio.length; i++){
portfolio[i] = { // <-- update the copy
ticker: portfolio[i].ticker,
avgPrice: portfolio[i].avgPrice,
count: portfolio[i].count
}
}
fs.collection('users')
.doc(...)
.update({ portfolio, ... })
.then(() => {
...some actions
});
}

How to set state in loop

I'm trying to import Wordpress categories from .cvs file. I'm writing a simple app in react and I've got a function:
componentDidUpdate( prevProps, prevState ) {
let that = this
if (prevState.syncStatus !== this.state.syncStatus && this.state.syncStatus == 'posts') {
row_terms.forEach( (element, inx) => {
let parent = that.state.parent_id;
let _terms = element.split('>')
_terms = _terms.map(function(e){return e.trim();});
const total = _terms.length
_terms.forEach( (_term, index) => {
addCategory(_term, that.state.parent_id).then(result => {
let term_id
if( result.code && result.code == 'term_exists' ) {
term_id = result.data.resource_id
} else {
term_id = result.id
}
if ( ( 1 + index ) === total ) {
categories.push(term_id)
} else {
that.setState({parent_id: term_id})
}
})
})
})
}
}
and addCategory:
import WooCommerce from './woocommerce'
async function addCategory(name, parent) {
console.log('parent', parent)
try {
return await WooCommerce.postAsync('products/categories', {name: name, parent: parent}).then(result => {
return JSON.parse(result.toJSON().body);
});
} catch (e) {
return e
}
}
export default addCategory
and initial value is set
constructor(props) {
super()
this.state = {
parent_id: 0,
}
}
I want to add cateogories one after another because I need to set parent_id for categories that are children. So when it adds a category and the condition
if ( ( 1 + index ) === total ) {
is not met I want to set parent_id and then use it in next iteration. But it doesn't work.
When I use
console.log(that.state.parent_id)
after
that.setState({parent_id: term_id})
It prints correct value.
When i run my app it prints 0 ( console.log in addCategory() ) for all categories before any request is made.
.forEach() isn't aware of the asynchronicity of addCategory; you'll either have to chain all of those thens, or preferably just use async/await and plain old for loops, which can be used with await without extra hoops to jump through.
Assuming you want to loop through all of the row_terms and process them, you'll also need to await on those promises...
const categories = [];
const promises = row_terms.map(async (element) => {
const terms = element.split(">").map((e) => e.trim());
const total = terms.length;
let parent = null;
for (let i = 0; i < total; i++) {
const term = terms[i];
const result = await addCategory(term, parent);
const term_id = result.code && result.code === "term_exists" ? result.data.resource_id : result.id;
if (i === total - 1) {
categories.push(term_id);
} else {
parent = term_id;
}
}
});
await Promise.all(promises);

Scroll bar keep returning to top in infinite scroll -React js

I have used following code in my component to load new data when scrolling.But when new page of data is loaded the scroll bar keeps returning to the top.I'm using this for Magento PWA with react.
const Category = props => {
const {id} = props;
const classes = mergeClasses(defaultClasses, props.classes);
const [paginationValues, paginationApi] = usePagination();
const {currentPage, totalPages} = paginationValues;
const {setCurrentPage, setTotalPages} = paginationApi;
const [selectedPageSize, setPageSize] = useState(40);
const [pageNumber, setPageNumber] = useState(1);
function handlePageSize() {
setPageNumber(pageNumber+1)
}
const sortProps = useSort();
const [currentSort] = sortProps;
const previousSort = useRef(currentSort);
const pageControl = {
currentPage,
setPage: setCurrentPage,
totalPages
};
const [runQuery, queryResponse] = useLazyQuery(GET_CATEGORY,{fetchPolicy:'cache-first'});
const {loading, error, data} = queryResponse;
const {search} = useLocation();
const bqueryResponsee = useQuery(
GET_ATTRIBUTES
);
let battributedata = '';
// Keep track of the search terms so we can tell when they change.
const previousSearch = useRef(search);
// Get "allowed" filters by intersection of schema and aggregations
const {data: introspectionData} = useQuery(FILTER_INTROSPECTION);
// Create a type map we can reference later to ensure we pass valid args
// to the graphql query.
// For example: { category_id: 'FilterEqualTypeInput', price: 'FilterRangeTypeInput' }
const filterTypeMap = useMemo(() => {
const typeMap = new Map();
if (introspectionData) {
introspectionData.__type.inputFields.forEach(({name, type}) => {
typeMap.set(name, type.name);
});
}
return typeMap;
}, [introspectionData]);
// Run the category query immediately and whenever its variable values change.
useEffect(() => {
window.addEventListener('scroll', infiniteScroll);
// Wait until we have the type map to fetch product data.
if (!filterTypeMap.size) {
return;
}
const filters = getFiltersFromSearch(search);
const newFilters = {};
newFilters['category_id'] = {eq: String(id)};
filters.forEach((values, key) => {
newFilters[key] = getFilterInput(values, filterTypeMap.get(key));
});
runQuery({
variables: {
currentPage: Number(pageNumber),
id: Number(id),
filters: newFilters,
pageSize: Number(selectedPageSize),
sort: {[currentSort.sortAttribute]: currentSort.sortDirection}
}
});
window.scrollTo({
left: 0,
top: 0,
behavior: 'smooth'
});
}, [
currentPage,
currentSort,
filterTypeMap,
id,
selectedPageSize,
runQuery,
search,
pageNumber
]);
const totalPagesFromData = data
? Math.ceil(data.category.product_count/selectedPageSize)
: null;
useEffect(() => {
setTotalPages(totalPagesFromData);
return () => {
setTotalPages(null);
};
}, [setTotalPages, totalPagesFromData]);
// If we get an error after loading we should try to reset to page 1.
// If we continue to have errors after that, render an error message.
useEffect(() => {
if (error && !loading && currentPage !== 1) {
setCurrentPage(1);
}
}, [currentPage, error, loading, setCurrentPage]);
// Reset the current page back to one (1) when the search string, filters
// or sort criteria change.
useEffect(() => {
// We don't want to compare page value.
const prevSearch = new URLSearchParams(previousSearch.current);
const nextSearch = new URLSearchParams(search);
prevSearch.delete('page');
nextSearch.delete('page');
if (
prevSearch.toString() !== nextSearch.toString() ||
previousSort.current.sortAttribute.toString() !==
currentSort.sortAttribute.toString() ||
previousSort.current.sortDirection.toString() !==
currentSort.sortDirection.toString()
) {
// The search term changed.
setCurrentPage(1);
// And update the ref.
previousSearch.current = search;
previousSort.current = currentSort;
}
}, [currentSort, previousSearch, search, setCurrentPage]);
if (error && currentPage === 1 && !loading) {
if (process.env.NODE_ENV !== 'production') {
console.error(error);
}
return <div>Data Fetch Error</div>;
}
// Show the loading indicator until data has been fetched.
if (totalPagesFromData === null) {
return fullPageLoadingIndicator;
}
if (typeof bqueryResponsee.data !== "undefined" && !bqueryResponsee.loading) {
battributedata = bqueryResponsee.data.customAttributeMetadata.items[0].attribute_options;
} else {
battributedata = [];
}
const count = totalPagesFromData ? totalPagesFromData : null;
const galleries = [];
if (count && count >= 1) {
for (let i =1;i<=pageNumber;i++) {
galleries.push(
<section className={classes.gallery}>
<Gallery searchItems={null} ID={1}
newSort={{[currentSort.sortAttribute]: currentSort.sortDirection}}
newFilters={newFiltersLazy}
currentPage={i} categoryId={id} pageSize={40} introspectionData={introspectionData}
battributedata={battributedata}/>
</section>
)
}
}
function infiniteScroll(){
console.log(Math.ceil((window.innerHeight + document.documentElement.scrollTop)/100)*100,Math.ceil((document.documentElement.offsetHeight*8/10)/100)*100)
// End of the document reached?
if ( Math.ceil((window.innerHeight + document.documentElement.scrollTop)/100)*100
>= Math.ceil((document.documentElement.offsetHeight*8/10)/100)*100){
handlePageSize()
}
}
return (
<Fragment>
<Meta name="description" content={metaDescription}/>
<CategoryContent
totalPagesFromData={totalPagesFromData}
categoryId={id}
classes={classes}
data={loading ? null : data}
pageControl={pageControl}
sortProps={sortProps}
onSelectSize={handlePageSize}
battributedata={battributedata}
selectedPageSize={selectedPageSize}
galleries={galleries}
newSort={{[currentSort.sortAttribute]: currentSort.sortDirection}}
newFilters={newFiltersLazy}
introspectionData={introspectionData}
pageNumber={pageNumber}
/>
</Fragment>
);
};
What I did here is created a new array galleries and the Gallery component in each page increment while scrolling and inside Gallery the items will be created.Problem is the scroll bar keep returning to the top in each increment.Please help

How to properly work with promises, Firebase and React's UseEffect hook?

Basically what I'm trying to achieve is to run some code only after a variable is not undefined anymore. However, I'm feeling very confused with the use of promises to await firebase responses, as well as with the use of React's useEffect hook.
I did some research that perhaps listeners are my answer to this? I couldn't really figure out how to implement them, though.
const weekday = moment().isoWeekday()
export const TimeGrid = () => {
const { userObject } = useContext(Context)
//(1) I wish to use the below to generate a list of times
const [LIST_OF_TIMES_FROM_DATABASE, SET_LIST_OF_TIMES_FROM_DATABASE] = useState([])
let businessId
function getBusinessId() {
if (userObject) businessId = userObject.businessId
}
getBusinessId()
//defines function that will run below inside of first useEffect
//also where the list of times is supposed to be set
function getWorkingHoursAccordingToDayOfTheWeek(day, snapshot) {
const workingHours = []
const ALL_AVAILABLE_TIMES = []
workingHours.push(snapshot.data().beginWeek)
workingHours.push(snapshot.data().endWeek)
const [begin, ending] = workingHours
let bgn = moment(begin, 'HH:mm')
const end = moment(ending, 'HH:mm')
let i = 0
while (bgn <= end) {
ALL_AVAILABLE_TIMES.push({
id: i,
type: 'time',
day: 'today',
time: bgn.format('HHmm'),
})
bgn = bgn.add(30, 'minutes')
i++
}
SET_LIST_OF_TIMES_FROM_DATABASE(ALL_AVAILABLE_TIMES) //(2) This is where I set the list, which won't work on its 1st run
}
useEffect(() => {
async function getTimesFromDB() {
const approved = await approvedBusinessService.doc(businessId)
const snapshotApproved = await approved.get()
if (snapshotApproved.exists) {
getWorkingHoursAccordingToDayOfTheWeek(weekday, snapshotApproved)
return
} else {
const pending = await businessPendingApprovalService.doc(businessId)
const snapshotPending = await pending.get()
if (snapshotPending.exists) {
getWorkingHoursAccordingToDayOfTheWeek(weekday, snapshotPending)
}
}
return
}
getTimesFromDB()
}, [userObject])
const allBookedTimes = allBookings.map(element => element.time)
//the below used to be 'listOfTimesJSON.map(item => item.time)' and used to work as it was a static JSON file
//(3) this is sometimes undefined... so all of the code below which relies on this will not run
const listOfTimes = LIST_OF_TIMES_FROM_DATABASE.map(item => item.time)
const [counts, setCounts] = useState({})
useEffect(() => {
const counts = {}
//(4) below will not work as listOfTimes won't exist (because of 'LIST_OF_TIMES_FROM_DATABASE' being undefined)
listOfTimes.forEach(x => {
counts[x] = (counts[x] || 0) + 1
if (allBookedTimes.includes(x)) counts[x] = counts[x] - 1
})
setCounts(counts)
}, [])
const sortedListOfTimesAndCount = Object.keys(counts).sort() //(5) undefined, because 'counts' was undefined.
const displayListOfTimes = sortedListOfTimesAndCount.map(
time =>
time > currentTime && (
<>
<li>
{time}
</li>
</>
),
)
return (
<div>
<ul>{displayListOfTimes}</ul>
</div>
)
}
as per the comments in your code your steps 3 ,4 ,5 are dependent on LIST_OF_TIMES_FROM_DATABASE
and it's also not in sequence,
And you are expecting it to execute in the sequence,
1) First, it will execute all the thing which is outside the useEffect and it's dependency whenever there is change in state, so keep that in mind
2) useEffect(() => {...},[]) this will get called as soon as component mounts, so in most cases, you will get listOfTimes as [], because at that time API call might be in requesting data from server.
3) There are few unnecessary things like const [counts, setCounts] = useState({}) and useEffect(() => {...} , []), this is kind of overuse of functionality.
Sometimes you can do the things simply but with all these it becomes complicated
Solution :
So what you can do is just put all the code inside displayListOfTimes function and check for LIST_OF_TIMES_FROM_DATABASE if available then and only then proceed with steps 3,4,5. So you will never get LIST_OF_TIMES_FROM_DATABASE undefined
NOTE : And as per the code LIST_OF_TIMES_FROM_DATABASE either be blank
array or array with data but never undefined, and if you are getting undefined then you can check that while setting up the state
const weekday = moment().isoWeekday()
export const TimeGrid = () => {
const { userObject } = useContext(Context)
//(1) I wish to use the below to generate a list of times
const [LIST_OF_TIMES_FROM_DATABASE, SET_LIST_OF_TIMES_FROM_DATABASE] = useState([])
let businessId
function getBusinessId() {
if (userObject) businessId = userObject.businessId
}
getBusinessId()
//defines function that will run below inside of first useEffect
//also where the list of times is supposed to be set
function getWorkingHoursAccordingToDayOfTheWeek(day, snapshot) {
const workingHours = []
const ALL_AVAILABLE_TIMES = []
workingHours.push(snapshot.data().beginWeek)
workingHours.push(snapshot.data().endWeek)
const [begin, ending] = workingHours
let bgn = moment(begin, 'HH:mm')
const end = moment(ending, 'HH:mm')
let i = 0
while (bgn <= end) {
ALL_AVAILABLE_TIMES.push({
id: i,
type: 'time',
day: 'today',
time: bgn.format('HHmm'),
})
bgn = bgn.add(30, 'minutes')
i++
}
SET_LIST_OF_TIMES_FROM_DATABASE(ALL_AVAILABLE_TIMES) //(2) This is where I set the list, which won't work on its 1st run
}
useEffect(() => {
async function getTimesFromDB() {
const approved = await approvedBusinessService.doc(businessId)
const snapshotApproved = await approved.get()
if (snapshotApproved.exists) {
getWorkingHoursAccordingToDayOfTheWeek(weekday, snapshotApproved)
return
} else {
const pending = await businessPendingApprovalService.doc(businessId)
const snapshotPending = await pending.get()
if (snapshotPending.exists) {
getWorkingHoursAccordingToDayOfTheWeek(weekday, snapshotPending)
}
}
return
}
getTimesFromDB()
}, [userObject])
const displayListOfTimes = () => { // <----- Start - HERE
if(LIST_OF_TIMES_FROM_DATABASE && LIST_OF_TIMES_FROM_DATABASE.length) {
const counts = {}
const allBookedTimes = allBookings.map(element => element.time)
//(3) ------ this will never be undefined
const listOfTimes = LIST_OF_TIMES_FROM_DATABASE.map(item => item.time)
//(4) ------ now it will work always
listOfTimes.forEach(x => {
counts[x] = (counts[x] || 0) + 1
if (allBookedTimes.includes(x)) counts[x] = counts[x] - 1
})
//(5) ------ now it will work
const sortedListOfTimesAndCount = Object.keys(counts).sort()
return sortedListOfTimesAndCount.map(
time =>
time > currentTime && (
<>
<li>
{time}
</li>
</>
),
)
} else {
return <li>Nothing to show for now</li>
}
}
return (
<div>
<ul>{displayListOfTimes}</ul>
</div>
)
}
The problem is because you useEffect which uses listOfTimes isn't being called when the listOfTimes value updates after a fetch request.
You can define listOfTimes within the useEffect and add a dependency on LIST_OF_TIMES_FROM_DATABASE
const [counts, setCounts] = useState({})
useEffect(() => {
// Defining it inside because if we don't and add allBookedTimes as a dependency then it will lead to an infinite look since references will change on each re-render
const allBookedTimes = allBookings.map(element => element.time)
const listOfTimes = LIST_OF_TIMES_FROM_DATABASE.map(item => item.time)
const counts = {}
listOfTimes.forEach(x => {
counts[x] = (counts[x] || 0) + 1
if (allBookedTimes.includes(x)) counts[x] = counts[x] - 1
})
setCounts(counts)
}, [LIST_OF_TIMES_FROM_DATABASE, allBookings]); // Add both dependencies. This will ensure that you update counts state when the state for times changes

React Hook not setting with useEffect

I'm using useEffect to fetch some data from Trello and set some states. First I grab the card I'm looking for and call setCard and setCardLocation. Everything is working fine. Then I get into my else case and no matter what I do setPublishDate will never be set, the loop continues to run. Why do all of these other hooks work but my last one doesn't? Thanks.
export default function Home(props) {
const [performedFetch, setPerformedFetch] = useState(false);
const [slug, setSlug] = useState(null);
const [cardLocation, setCardLocation] = useState(1);
const [card, setCard] = useState(null);
const [publishDate, setPublishDate] = useState(null);
const key = ''; // imagine these are here
const token = '';
useEffect(() => {
setSlug(
new URLSearchParams(window.location.search).get('slug')
);
if (!performedFetch && !!slug) {
fetch(`https://api.trello.com/1/lists/${listId}/cards?key=${key}&token=${token}`)
.then(response => response.json())
.then(data => {
setPerformedFetch(true);
data.forEach((c, index) => {
if (c.desc.includes(slug)) {
setCard(c)
setCardLocation(index + 1)
} else if (!publishDate && index > cardLocation) {
console.log(publishDate); // why is this always null?? also runs multiple times
const name = c.name;
const frontHalf = name.split("/")[0].split(" ");
const month = frontHalf[frontHalf.length - 1];
const day = name.split("/")[1].split(")")[0];
setPublishDate(`${month}/${day}`);
}
});
});
}
});
As already mentioned by #TaghiKhavari, you should have two useEffects (Multiple effects to separate concerns).
Also, it is important to optimize the performance by skipping effects by providing a dependency array as second argument to the useEffect. So the effect will only re-run if any of its dependencies would change.
First effect for slug:
useEffect(() => {
setSlug(
new URLSearchParams(window.location.search).get('slug')
);
}, []) // Note: Remove "[]" if you want to set slug at each update / render Or keep it if you want to set it only once (at mount)
Second effect to fetch and set card and other details:
useEffect(() => {
if (!performedFetch && slug) {
fetch(
`https://api.trello.com/1/lists/${listId}/cards?key=${key}&token=${token}`
)
.then((response) => response.json())
.then((data) => {
setPerformedFetch(true)
// Note: if there can be only ONE matching card
const index = data.findIndex((card) => card.desc.includes(slug))
if (index > -1) {
const card = data[index]
setCard(card)
setCardLocation(index + 1)
const name = card.name
const frontHalf = name.split('/')[0].split(' ')
const month = frontHalf[frontHalf.length - 1]
const day = name.split('/')[1].split(')')[0]
setPublishDate(`${month}/${day}`)
}
// Setting State in a LOOP? is a problem
/*
data.forEach((card, index) => {
if (card.desc.includes(slug)) {
setCard(card)
setCardLocation(index + 1)
} else if (!publishDate && index > cardLocation) {
const name = card.name
const frontHalf = name.split('/')[0].split(' ')
const month = frontHalf[frontHalf.length - 1]
const day = name.split('/')[1].split(')')[0]
setPublishDate(`${month}/${day}`)
}
})*/
})
}
}, [slug, performedFetch])
Set states may be async to improve performance:
So, you should not set states in a loop as you are doing currently. If you must iterate through a loop and set all or few elements of the array in state, you can loop through the array and push all relevant items in a local array variable and set it to state after loop ends. Hope it helps!
It's because usually react states updates asynchronously and at the time you're checking for slug it hasn't set yet
you need to do something like this:
function Home(props) {
const [performedFetch, setPerformedFetch] = useState(false);
const [slug, setSlug] = useState(null);
const [cardLocation, setCardLocation] = useState(1);
const [card, setCard] = useState(null);
const [publishDate, setPublishDate] = useState(null);
const key = ""; // imagine these are here
const token = "";
useEffect(() => {
setSlug(new URLSearchParams(window.location.search).get("slug"));
});
useEffect(() => {
console.log(slug)
if (!performedFetch && !!slug) {
fetch(`https://api.trello.com/1/lists/${listId}/cards?key=${key}&token=${token}`)
.then(response => response.json())
.then(data => {
setPerformedFetch(true);
data.forEach((c, index) => {
if (c.desc.includes(slug)) {
setCard(c)
setCardLocation(index + 1)
} else if (!publishDate && index > cardLocation) {
console.log(publishDate); // why is this always null?? also runs multiple times
const name = c.name;
const frontHalf = name.split("/")[0].split(" ");
const month = frontHalf[frontHalf.length - 1];
const day = name.split("/")[1].split(")")[0];
setPublishDate(`${month}/${day}`);
}
});
});
}
}, [slug, performedFetch])
}

Categories

Resources