Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions examples/hackernews/src/components/comment/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,19 @@ import { fetchItem } from '../../services';
import { pluralize, timeAgo } from '../../utils';
import styles from './index.module.less';

export default function Comment({ id, itemsById }) {
interface CommentProps {
id: number;
}

interface CommentType {
by: string;
time: number;
text: string;
kids?: number[];
}
export default function Comment({ id }: CommentProps) {
const [open, setOpen] = useState(true);
const [comment, setComment] = useState(null);
const [comment, setComment] = useState<CommentType | null>(null);

useEffect(() => {
async function fetchComments() {
Expand Down Expand Up @@ -45,9 +55,7 @@ export default function Comment({ id, itemsById }) {
/>
<div className={styles.commentChildren}>
{comment.kids && open
? comment.kids.map((id) => (
<Comment key={id} id={id} itemsById={itemsById} />
))
? comment.kids.map((id) => <Comment key={id} id={id} />)
: null}
</div>
</div>
Expand Down
63 changes: 21 additions & 42 deletions examples/hackernews/src/components/item-list/index.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,29 @@
import { useContext, useEffect, useMemo, useState } from 'react';
import { Link } from '@umijs/tnf/router';
import { Context } from '../../context';
import { fetchIdsByType, fetchItems } from '../../services';
import React, { Link } from '@umijs/tnf/router';
import type { ItemProps } from '../../types';
import Item from '../item';
import Loading from '../loading';
import styles from './index.module.less';

export default function ItemList({ type, page }) {
const { dispatch } = useContext(Context);
const [lists, setLists] = useState({
top: [],
new: [],
show: [],
ask: [],
job: [],
});
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(true);

const itemsPerPage = 20;
const maxPage = useMemo(
() => Math.ceil(lists[type].length / itemsPerPage),
[lists],
);

useEffect(() => {
async function fetchList() {
const ids = await fetchIdsByType(type);
setLists({ ...lists, [type]: ids });
const items = await fetchItems(
ids.slice(itemsPerPage * (page - 1), itemsPerPage * page),
);
const itemsById = items.reduce((_memo, item) => {
const memo = _memo;
memo[item.id] = item;
return memo;
}, {});
setLoading(false);
setItems(items);
dispatch({ type: 'saveItems', payload: itemsById });
}
interface ItemListProps {
type: keyof Lists;
page: number;
maxPage: number;
items: ItemProps[];
}

fetchList();
}, [page]);
interface Lists {
top: number[];
new: number[];
show: number[];
ask: number[];
job: number[];
}

export default function ItemList({
type,
items,
page,
maxPage,
}: ItemListProps) {
return (
<>
<div className={styles.nav}>
Expand All @@ -65,7 +45,6 @@ export default function ItemList({ type, page }) {
</div>

<div className={styles.list}>
<Loading loading={loading} />
{items.map((item) => (
<Item key={item.id} item={item} />
))}
Expand Down
9 changes: 4 additions & 5 deletions examples/hackernews/src/components/item-page/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Link } from '@umijs/tnf/router';
import React, { Link } from '@umijs/tnf/router';
import type { ItemProps } from '../../types';
import { host, timeAgo } from '../../utils';
import Comment from '../comment';
import styles from './index.module.less';

export default function ItemPage({ item, itemsById }) {
export default function ItemPage({ item }: { item: ItemProps }) {
if (!item) return null;
return (
<>
Expand All @@ -26,9 +27,7 @@ export default function ItemPage({ item, itemsById }) {
</p>
<div className={styles.commentChildren}>
{item.kids
? item.kids.map((id) => (
<Comment key={id} id={id} itemsById={itemsById} />
))
? item.kids.map((id) => <Comment key={id} id={id} />)
: null}
</div>
</div>
Expand Down
19 changes: 16 additions & 3 deletions examples/hackernews/src/components/item/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
import { Link } from '@umijs/tnf/router';
import React, { Link } from '@umijs/tnf/router';
import { host, timeAgo } from '../../utils';
import styles from './index.module.less';

export default function Item({ item }) {
interface ItemProps {
item: {
score: number;
title: string;
url?: string;
type: string;
id: number;
by: string;
descendants: number;
time: number;
};
}

export default function Item({ item }: ItemProps) {
const { score, title, url, type, id, by, descendants, time } = item;

return (
Expand All @@ -17,7 +30,7 @@ export default function Item({ item }) {
<span className={styles.host}> ({host(url)})</span>
</span>
) : (
<Link to={`/item/$id`} params={{ id }} state={{ item }}>
<Link to={`/item/$id`} params={{ id }}>
{title}
</Link>
)}
Expand Down
11 changes: 8 additions & 3 deletions examples/hackernews/src/components/loading/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import React from 'react';
import classnames from 'classnames';
import styles from './index.module.less';

function Spinner({ loading }) {
interface SpinnerProps {
loading: boolean;
}

function Spinner({ loading }: SpinnerProps) {
const svgCls = classnames({
[styles.spinner]: true,
[styles.show]: loading,
[styles.spinner as string]: true,
[styles.show as string]: loading,
});
return (
<div>
Expand Down
16 changes: 9 additions & 7 deletions examples/hackernews/src/components/user-page/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { useEffect, useState } from 'react';
import { fetchUser } from '../../services';
import React from 'react';
import { timeAgo } from '../../utils';
import styles from './index.module.less';

export default function UserPage({ id }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser(id).then((user) => setUser(user));
}, []);
interface User {
id: string;
created: number;
karma: number;
about?: string;
}

export default function UserPage({ user }: { user: User }) {
if (!user) return null;
return (
<div className={styles.normal}>
Expand Down
17 changes: 0 additions & 17 deletions examples/hackernews/src/context/index.tsx

This file was deleted.

9 changes: 2 additions & 7 deletions examples/hackernews/src/pages/__root.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import React, { useReducer } from 'react';
import { Link, Outlet, createRootRoute } from '@umijs/tnf/router';
import { Context, initialState, reducer } from '../context';
import React, { Link, Outlet, createRootRoute } from '@umijs/tnf/router';
import '../global.less';
import styles from './index.module.less';

export const Route = createRootRoute({
component: () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
<div className={styles.header}>
Expand Down Expand Up @@ -66,9 +63,7 @@ export const Route = createRootRoute({
</div>
</div>
<div className={styles.view}>
<Context.Provider value={{ state, dispatch }}>
<Outlet />
</Context.Provider>
<Outlet />
</div>
</>
);
Expand Down
10 changes: 9 additions & 1 deletion examples/hackernews/src/pages/ask/$page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import React, { createFileRoute } from '@umijs/tnf/router';
import ItemList from '../../components/item-list';
import { fetchList } from '../../services/api';
import type { Params } from '../../types';

export const Route = createFileRoute('/ask/$page')({
component: AskComponent,
loader: async ({ params }: { params: Params }) =>
await fetchList('ask', Number(params.page)),
});

function AskComponent() {
const { page } = Route.useParams();
return <ItemList type="ask" page={Number(page)} />;
const { items, maxPage } = Route.useLoaderData();

return (
<ItemList type="ask" page={Number(page)} maxPage={maxPage} items={items} />
);
}
12 changes: 9 additions & 3 deletions examples/hackernews/src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { createFileRoute } from '@umijs/tnf/router';
import React, { createFileRoute } from '@umijs/tnf/router';
import ItemList from '../components/item-list';
import { fetchList } from '../services/api';
import type { Params } from '../types';

export const Route = createFileRoute('/')({
component: TopComponent,
loader: async ({ params }: { params: Params }) =>
await fetchList('top', Number(params?.page ?? '1') ?? 1),
});

function TopComponent() {
const page = Number(Route.useParams()?.page ?? '1') ?? 1;
const params = Route.useParams<Params>();
const page = Number(params?.page ?? '1') ?? 1;
const { items, maxPage } = Route.useLoaderData();

return <ItemList type="top" page={page} />;
return <ItemList type="top" page={page} maxPage={maxPage} items={items} />;
}
14 changes: 6 additions & 8 deletions examples/hackernews/src/pages/item/$itemId.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import React, { useContext } from 'react';
import { createFileRoute } from '@umijs/tnf/router';
import React, { createFileRoute } from '@umijs/tnf/router';
import ItemPage from '../../components/item-page';
import { Context } from '../../context';
import { fetchItem } from '../../services';

export const Route = createFileRoute('/item/$itemId')({
component: Item,
loader: async ({ params }: { params: { itemId: string } }) =>
await fetchItem(params.itemId),
});

function Item() {
const { itemId } = Route.useParams();
const { state } = useContext(Context);
return (
<ItemPage item={state.itemsById[itemId]} itemsById={state.itemsById} />
);
const item = Route.useLoaderData();
return <ItemPage item={item} />;
}
10 changes: 9 additions & 1 deletion examples/hackernews/src/pages/job/$page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import React, { createFileRoute } from '@umijs/tnf/router';
import ItemList from '../../components/item-list';
import { fetchList } from '../../services/api';
import type { Params } from '../../types';

export const Route = createFileRoute('/job/$page')({
component: JobComponent,
loader: async ({ params }: { params: Params }) =>
await fetchList('job', Number(params.page)),
});

function JobComponent() {
const { page } = Route.useParams();
return <ItemList type="job" page={Number(page)} />;
const { items, maxPage } = Route.useLoaderData();

return (
<ItemList type="job" page={Number(page)} maxPage={maxPage} items={items} />
);
}
10 changes: 9 additions & 1 deletion examples/hackernews/src/pages/new/$page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import React, { createFileRoute } from '@umijs/tnf/router';
import ItemList from '../../components/item-list';
import { fetchList } from '../../services/api';
import type { Params } from '../../types';

export const Route = createFileRoute('/new/$page')({
component: NewComponent,
loader: async ({ params }: { params: Params }) =>
await fetchList('new', Number(params.page)),
});

function NewComponent() {
const { page } = Route.useParams();
return <ItemList type="new" page={Number(page)} />;
const { items, maxPage } = Route.useLoaderData();

return (
<ItemList type="new" page={Number(page)} maxPage={maxPage} items={items} />
);
}
10 changes: 9 additions & 1 deletion examples/hackernews/src/pages/show/$page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import React, { createFileRoute } from '@umijs/tnf/router';
import ItemList from '../../components/item-list';
import { fetchList } from '../../services/api';
import type { Params } from '../../types';

export const Route = createFileRoute('/show/$page')({
component: ShowComponent,
loader: async ({ params }: { params: Params }) =>
await fetchList('show', Number(params.page)),
});

function ShowComponent() {
const { page } = Route.useParams();
return <ItemList type="show" page={Number(page)} />;
const { items, maxPage } = Route.useLoaderData();

return (
<ItemList type="show" page={Number(page)} maxPage={maxPage} items={items} />
);
}
Loading
Loading