I have error 404 not found when refresh page with dynamic routes ini next js, my structure page is like below:
pages
[storeName]
summaries.jsx
[store-insight].jsx
when I’m in [store-insight].jsx
I need the query in url to be used in hitting an api. for example www.url.com/storName/10
, I use the 10
in an api body
here is the code in [store-insight].jsx
:
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
import { BackButton } from '../../components/button/BackButton';
import Navbar from '../../components/Navbar';
import { useSelector } from 'react-redux';
import { StoreInsightHeader } from '../../components/storeInsight/StoreInsightHeader';
import { KeyValueInsight } from '../../components/storeInsight/KeyValueInsight';
import { StoreInsightSummaryChart } from '../../components/storeInsight/StoreInsightSummaryChart';
const StoreInsight = () => {
const { back, query } = useRouter();
const router = useRouter();
const {
store,
filterReport,
revenuInsight,
featuresInsight,
productInsight,
browsingInsight,
operationalGraph,
} = useSelector((store) => store);
// const { detailStore } = store;
// const { name, country_code, location } = detailStore;
const [storeDetail, setStoreDetail] = useState({});
const storeDetails = () => {
const splitted = query['store-insight']?.split('&');
setStoreDetail((prev) => {
return {
...prev,
id: splitted[0],
storeName: splitted[1],
storeLocation: splitted[2],
storeLogo: splitted[3],
};
});
};
useEffect(() => {
if (query['store-insight']?.length > 0) storeDetails();
}, [query, storeDetail?.id]);
return (
<>
<div className='bg-white'>
<Navbar storeLogo={storeDetail?.storeLogo} />
</div>
<div className='m-6 flex flex-1 flex-row items-center space-x-3'>
<BackButton
onClick={() => {
router.push({
pathname: `/${query?.storeName}/summaries`,
query: { date: filterReport?.filter },
});
localStorage.removeItem('storeDetail');
}}
className={'h-3 w-3'}
/>
<label className='text-[10px] font-bold'>
Back to Account Level Insights
</label>
</div>
<div className='bg-white p-4 rounded-lg mx-4'>
<StoreInsightHeader
storeName={`${storeDetail?.storeName} ${storeDetail?.storeLocation}`}
/>
<KeyValueInsight />
<StoreInsightSummaryChart />
</div>
</>
);
};
export default StoreInsight;
also used in <KeyValueInsight />
component ini [store-insight].jsx
page like below:
import { useRouter } from 'next/router';
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
setKeyInsight,
setValueCreated,
} from '../../features/InsightV2/storeMetricSlice';
import { key_value_insight } from '../../resource/dummy-data';
import { getStoreMetric } from '../../services/insightV2/storeMetric';
import { KeyValueInsightCard } from '../card/KeyValueInsightCard';
import BrowsingInterestSkeleton from '../skeleton/BrowsingInterest';
import { convertInputPrice } from '../../helper/priceConverter';
export const KeyValueInsight = () => {
const { query } = useRouter();
const dispatch = useDispatch();
const { store, filterReport, storeMetric } = useSelector((store) => store);
const { filter, custom_date } = filterReport;
const { key_insight, value_created } = storeMetric;
const [loading, setLoading] = useState(false);
const [storeDetail, setStoreDetail] = useState({});
const storeDetails = () => {
const splitted = query['store-insight']?.length && query['store-insight']?.split('&');
setStoreDetail((prev) => {
return {
...prev,
id: splitted[0],
storeName: splitted[1],
storeLocation: splitted[2],
storeLogo: splitted[3],
};
});
};
const currency = () => {
if (storeDetail?.storeName === 'al-ikhsan') {
return `MYR`;
} else {
return `SGD`;
}
};
const fetchData = async () => {
try {
setLoading(true);
if (filter === 'custom') {
const { data } = await getStoreMetric({
days: filter,
storeId: storeDetail?.id,
customStart: custom_date?.custom_start,
customeEnd: custom_date?.custom_end,
});
if (data) {
dispatch(setKeyInsight(data?.key_insight));
dispatch(setValueCreated(data?.value_created));
}
} else {
const { data } = await getStoreMetric({
days: filter,
storeId: storeDetail?.id,
});
if (data) {
dispatch(setKeyInsight(data?.key_insight));
dispatch(setValueCreated(data?.value_created));
}
}
} catch (error) {
console.log('store metric chart log <<<<<<', error);
} finally {
setLoading(false);
}
};
useEffect(() => {
if (query['store-insight']?.length > 0) storeDetails();
}, [query]);
useEffect(() => {
if (storeDetail?.id) fetchData();
}, [storeDetail?.id, filter, custom_date]);
return (
<div className='grid grid-cols-2 mt-4 gap-x-4'>
<div className='p-4 rounded-lg border'>
<div className='font-semibold text-xs mb-4'>Key Insights</div>
{loading ? (
<BrowsingInterestSkeleton />
) : (
<div className='grid text-center grid-cols-4 gap-x-4'>
<KeyValueInsightCard
title={'Capture'}
value={key_insight?.capture?.value || 'WIP'}
/>
<KeyValueInsightCard
title={'Browsing'}
value={key_insight?.browsing?.value || 'WIP'}
/>
<KeyValueInsightCard
title={'Leads'}
value={key_insight?.leads?.value || 'WIP'}
/>
<KeyValueInsightCard
title={'Conversion'}
value={key_insight?.conversion?.value || 'WIP'}
/>
</div>
)}
</div>
<div className='p-4 rounded-lg border'>
<div className='font-semibold text-xs mb-4'>Value Created</div>
{loading ? (
<BrowsingInterestSkeleton />
) : (
<div className='grid text-center grid-cols-4 gap-x-4'>
<KeyValueInsightCard
title={'Shoppers Served'}
value={
convertInputPrice(`${value_created?.shoppers_served?.value}`) ||
'WIP'
}
/>
<KeyValueInsightCard
title={'Time Saved'}
value={
convertInputPrice(`${value_created?.time_saved?.value}`) +
` min`
}
/>
<KeyValueInsightCard
title={'Shoppers Acquired'}
value={value_created?.shoppers_acquired?.value || 'WIP'}
/>
<KeyValueInsightCard
title={'Sales Generated'}
value={
`${currency()} ${parseFloat(
value_created?.sales_generated?.value,
).toFixed()}.00` || 'WIP'
}
/>
</div>
)}
</div>
</div>
);
};