refactor: destructure loaderData in multiple components for cleaner code

This commit is contained in:
Ardeman 2025-03-09 09:32:51 +08:00
parent 09e5f84b8b
commit 0da2006e78
20 changed files with 34 additions and 42 deletions

View File

@ -36,7 +36,7 @@ const DESCRIPTIONS: DescriptionMap = {
export const SuccessModal = ({ isOpen, onClose }: ModalProperties) => { export const SuccessModal = ({ isOpen, onClose }: ModalProperties) => {
const { setIsLoginOpen, setIsSubscribeOpen } = useNewsContext() const { setIsLoginOpen, setIsSubscribeOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_news') const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData const { userData } = loaderData || {}
const message = isOpen const message = isOpen
? DESCRIPTIONS[isOpen] ? DESCRIPTIONS[isOpen]

View File

@ -12,7 +12,7 @@ import { getPremiumAttribute } from '~/utils/render'
export const CarouselHero = (properties: TNews) => { export const CarouselHero = (properties: TNews) => {
const { setIsSuccessOpen } = useNewsContext() const { setIsSuccessOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_news') const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData const { userData } = loaderData || {}
const { title, description, items } = properties const { title, description, items } = properties
const [emblaReference, emblaApi] = useEmblaCarousel({ loop: false }) const [emblaReference, emblaApi] = useEmblaCarousel({ loop: false })

View File

@ -12,7 +12,7 @@ import { getPremiumAttribute } from '~/utils/render'
export const CarouselSection = (properties: TNews) => { export const CarouselSection = (properties: TNews) => {
const { setIsSuccessOpen } = useNewsContext() const { setIsSuccessOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_news') const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData const { userData } = loaderData || {}
const { title, description, items } = properties const { title, description, items } = properties
const [emblaReference, emblaApi] = useEmblaCarousel({ const [emblaReference, emblaApi] = useEmblaCarousel({
loop: false, loop: false,

View File

@ -12,7 +12,7 @@ import { getPremiumAttribute } from '~/utils/render'
export const CategorySection = (properties: TNews) => { export const CategorySection = (properties: TNews) => {
const { setIsSuccessOpen } = useNewsContext() const { setIsSuccessOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_news') const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData const { userData } = loaderData || {}
const { title, description, items } = properties const { title, description, items } = properties

View File

@ -8,7 +8,7 @@ import type { loader } from '~/routes/_admin.lg-admin'
export const Navbar = () => { export const Navbar = () => {
const loaderData = useRouteLoaderData<typeof loader>('routes/_admin.lg-admin') const loaderData = useRouteLoaderData<typeof loader>('routes/_admin.lg-admin')
const staffData = loaderData?.staffData const { staffData } = loaderData || {}
const fetcher = useFetcher() const fetcher = useFetcher()
return ( return (

View File

@ -43,7 +43,7 @@ export const FormRegister = () => {
const [disabled, setDisabled] = useState(false) const [disabled, setDisabled] = useState(false)
const fetcher = useFetcher() const fetcher = useFetcher()
const loaderData = useRouteLoaderData<typeof loader>('routes/_news') const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const subscriptions = loaderData?.subscriptionsData const { subscriptionsData: subscriptions } = loaderData || {}
const formMethods = useRemixForm<TRegisterSchema>({ const formMethods = useRemixForm<TRegisterSchema>({
mode: 'onSubmit', mode: 'onSubmit',

View File

@ -31,7 +31,7 @@ export default function FormSubscription() {
const [error, setError] = useState<string>() const [error, setError] = useState<string>()
const [disabled, setDisabled] = useState(false) const [disabled, setDisabled] = useState(false)
const loaderData = useRouteLoaderData<typeof loader>('routes/_news') const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const subscriptions = loaderData?.subscriptionsData const { subscriptionsData: subscriptions } = loaderData || {}
const formMethods = useRemixForm<TSubscribeSchema>({ const formMethods = useRemixForm<TSubscribeSchema>({
mode: 'onSubmit', mode: 'onSubmit',

View File

@ -18,7 +18,7 @@ export default function HeaderMenuMobile(properties: THeaderMenuMobile) {
const [isMenuOpen, setIsMenuOpen] = useState(false) const [isMenuOpen, setIsMenuOpen] = useState(false)
const { setIsLoginOpen } = useNewsContext() const { setIsLoginOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_news') const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData const { userData } = loaderData || {}
const fetcher = useFetcher() const fetcher = useFetcher()
const handleToggleMenu = (): void => { const handleToggleMenu = (): void => {

View File

@ -8,7 +8,7 @@ import type { loader } from '~/routes/_news'
export const HeaderTop = () => { export const HeaderTop = () => {
const { setIsLoginOpen } = useNewsContext() const { setIsLoginOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_news') const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData const { userData } = loaderData || {}
const fetcher = useFetcher() const fetcher = useFetcher()
return ( return (

View File

@ -11,7 +11,7 @@ export const CategoriesPage = () => {
const loaderData = useRouteLoaderData<typeof loader>( const loaderData = useRouteLoaderData<typeof loader>(
'routes/_admin.lg-admin._dashboard.categories._index', 'routes/_admin.lg-admin._dashboard.categories._index',
) )
const categoriesData = loaderData?.dataCategories const { dataCategories: categoriesData } = loaderData || {}
DataTable.use(DT) DataTable.use(DT)
const dataTable = categoriesData?.sort((a, b) => { const dataTable = categoriesData?.sort((a, b) => {

View File

@ -15,7 +15,7 @@ export const ContentsPage = () => {
const loaderData = useRouteLoaderData<typeof loader>( const loaderData = useRouteLoaderData<typeof loader>(
'routes/_admin.lg-admin._dashboard.contents._index', 'routes/_admin.lg-admin._dashboard.contents._index',
) )
const newsData = loaderData?.newsData const { newsData } = loaderData || {}
DataTable.use(DT) DataTable.use(DT)
const dataTable = newsData?.sort( const dataTable = newsData?.sort(

View File

@ -11,8 +11,7 @@ export const TagsPage = () => {
const loaderData = useRouteLoaderData<typeof loader>( const loaderData = useRouteLoaderData<typeof loader>(
'routes/_admin.lg-admin._dashboard.tags._index', 'routes/_admin.lg-admin._dashboard.tags._index',
) )
const tagsData = loaderData?.tagsData const { tagsData: dataTable } = loaderData || {}
const dataTable = tagsData
DataTable.use(DT) DataTable.use(DT)
const dataColumns = [ const dataColumns = [

View File

@ -65,8 +65,8 @@ export const FormContentsPage = (properties: TProperties) => {
const fetcher = useFetcher() const fetcher = useFetcher()
const navigate = useNavigate() const navigate = useNavigate()
const loaderData = useRouteLoaderData<typeof loader>('routes/_admin.lg-admin') const loaderData = useRouteLoaderData<typeof loader>('routes/_admin.lg-admin')
const categories = loaderData?.categoriesData const { categoriesData: categories } = loaderData || {}
const tags = loaderData?.tagsData const { tagsData: tags } = loaderData || {}
const [error, setError] = useState<string>() const [error, setError] = useState<string>()
const [disabled, setDisabled] = useState(false) const [disabled, setDisabled] = useState(false)

View File

@ -15,9 +15,8 @@ export const NewsDetailPage = () => {
'routes/_news.detail.$slug', 'routes/_news.detail.$slug',
) )
const currentUrl = globalThis.location const currentUrl = globalThis.location
const { newsDetailData } = loaderData || {}
const { title, content, featured_image, author, live_at, tags } = const { title, content, featured_image, author, live_at, tags } =
newsDetailData || {} loaderData?.newsDetailData || {}
const { text } = useReadingTime(content || '') const { text } = useReadingTime(content || '')

View File

@ -1,14 +1,10 @@
import { getCategories } from '~/apis/common/get-categories' import { getCategories } from '~/apis/common/get-categories'
import { handleCookie } from '~/libs/cookies'
import { FormCategoryPage } from '~/pages/form-category' import { FormCategoryPage } from '~/pages/form-category'
import type { Route } from './+types/_admin.lg-admin._dashboard.categories.update.$id' import type { Route } from './+types/_admin.lg-admin._dashboard.categories.update.$id'
export const loader = async ({ request, params }: Route.LoaderArgs) => { export const loader = async ({ params }: Route.LoaderArgs) => {
const { staffToken } = await handleCookie(request) const { data: categoriesData } = await getCategories()
const { data: categoriesData } = await getCategories({
accessToken: staffToken,
})
const categoryData = categoriesData.find( const categoryData = categoriesData.find(
(category) => category.id === params.id, (category) => category.id === params.id,
) )
@ -18,7 +14,7 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => {
const DashboardCategoriesUpdateLayout = ({ const DashboardCategoriesUpdateLayout = ({
loaderData, loaderData,
}: Route.ComponentProps) => { }: Route.ComponentProps) => {
const categoryData = loaderData.categoryData const { categoryData } = loaderData || {}
return <FormCategoryPage categoryData={categoryData} /> return <FormCategoryPage categoryData={categoryData} />
} }
export default DashboardCategoriesUpdateLayout export default DashboardCategoriesUpdateLayout

View File

@ -14,7 +14,7 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => {
} }
const DashboardContentUpdateLayout = ({ loaderData }: Route.ComponentProps) => { const DashboardContentUpdateLayout = ({ loaderData }: Route.ComponentProps) => {
const newsData = loaderData.newsData const { newsData } = loaderData || {}
return <FormContentsPage newsData={newsData} /> return <FormContentsPage newsData={newsData} />
} }
export default DashboardContentUpdateLayout export default DashboardContentUpdateLayout

View File

@ -1,13 +1,10 @@
import { getTags } from '~/apis/common/get-tags' import { getTags } from '~/apis/common/get-tags'
import { handleCookie } from '~/libs/cookies'
import { TagsPage } from '~/pages/dashboard-tags' import { TagsPage } from '~/pages/dashboard-tags'
import type { Route } from './+types/_admin.lg-admin._dashboard.tags._index' import type { Route } from './+types/_admin.lg-admin._dashboard.tags._index'
export const loader = async ({ request }: Route.LoaderArgs) => {
const { staffToken } = await handleCookie(request) export const loader = async ({}: Route.LoaderArgs) => {
const { data: tagsData } = await getTags({ const { data: tagsData } = await getTags()
accessToken: staffToken,
})
return { tagsData } return { tagsData }
} }

View File

@ -14,7 +14,7 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => {
} }
const DashboardTagUpdateLayout = ({ loaderData }: Route.ComponentProps) => { const DashboardTagUpdateLayout = ({ loaderData }: Route.ComponentProps) => {
const tagData = loaderData.tagData const { tagData } = loaderData || {}
return <FormTagPage tagData={tagData} /> return <FormTagPage tagData={tagData} />
} }
export default DashboardTagUpdateLayout export default DashboardTagUpdateLayout

View File

@ -1,5 +1,16 @@
import { getCategories } from '~/apis/common/get-categories'
import { NewsCategoriesPage } from '~/pages/news-categories' import { NewsCategoriesPage } from '~/pages/news-categories'
import type { Route } from './+types/_news.category.$code'
export const loader = async ({ params }: Route.LoaderArgs) => {
const { data: categoriesData } = await getCategories()
const categoryData = categoriesData.find(
(category) => category.id === params.id,
)
return { categoryData }
}
const NewsCategoriesLayout = () => <NewsCategoriesPage /> const NewsCategoriesLayout = () => <NewsCategoriesPage />
export default NewsCategoriesLayout export default NewsCategoriesLayout

View File

@ -1,5 +1,4 @@
import { getNewsBySlug } from '~/apis/common/get-news-by-slug' import { getNewsBySlug } from '~/apis/common/get-news-by-slug'
import { getUser } from '~/apis/news/get-user'
import { APP } from '~/configs/meta' import { APP } from '~/configs/meta'
import { handleCookie } from '~/libs/cookies' import { handleCookie } from '~/libs/cookies'
import { NewsDetailPage } from '~/pages/news-detail' import { NewsDetailPage } from '~/pages/news-detail'
@ -8,14 +7,6 @@ import type { Route } from './+types/_news.detail.$slug'
export const loader = async ({ request, params }: Route.LoaderArgs) => { export const loader = async ({ request, params }: Route.LoaderArgs) => {
const { userToken } = await handleCookie(request) const { userToken } = await handleCookie(request)
let userData
if (userToken) {
const { data } = await getUser({
accessToken: userToken,
})
userData = data
}
// TODO: need handle if user not access non premium data
const { data: newsDetailData } = await getNewsBySlug({ const { data: newsDetailData } = await getNewsBySlug({
slug: params.slug, slug: params.slug,
accessToken: userToken, accessToken: userToken,
@ -23,7 +14,6 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => {
return { return {
newsDetailData, newsDetailData,
userData,
} }
} }