김재형

Implement FileList component

1 -import React, { Fragment } from "react"; 1 +import React, { useEffect } from "react";
2 -import { Switch, Route, Redirect } from "react-router-dom"; 2 +import { Switch, Route, Redirect, useHistory } from "react-router-dom";
3 3
4 import { Login } from "auth/Login"; 4 import { Login } from "auth/Login";
5 -import { useAuth } from "auth/useAuth"; 5 +import { useAuth, TokenContext } from "auth/useAuth";
6 +
7 +import { Page } from "layout/Page";
8 +import { FileList } from "file/FileList";
6 9
7 export function App() { 10 export function App() {
8 const { token, login } = useAuth(); 11 const { token, login } = useAuth();
12 + const root = token?.user.rootFolder;
13 + const history = useHistory();
14 +
15 + useEffect(() => {
16 + if (root) {
17 + history.push(`/folder/${root}`);
18 + }
19 + }, [history, root]);
20 +
9 return ( 21 return (
10 - <Fragment>
11 <Switch> 22 <Switch>
12 <Route path="/login"> 23 <Route path="/login">
13 <Login login={login} /> 24 <Login login={login} />
14 </Route> 25 </Route>
26 + <Route>
27 + {token !== null ? (
28 + <TokenContext.Provider value={token}>
29 + <Page>
30 + <Switch>
31 + <Route path="/folder/:id">
32 + <FileList />
33 + </Route>
34 + </Switch>
35 + </Page>
36 + </TokenContext.Provider>
37 + ) : (
38 + <Redirect to="/login" />
39 + )}
40 + </Route>
15 </Switch> 41 </Switch>
16 - {token === null && <Redirect to="/login" />}
17 - </Fragment>
18 ); 42 );
19 } 43 }
......
1 +import React from "react";
2 +import { useParams } from "react-router-dom";
3 +import { useFileList } from "./useFileList";
4 +
5 +export function FileList() {
6 + const id = useParams<{ id: string }>().id;
7 + const { data } = useFileList(id);
8 +
9 + return <div>{JSON.stringify(data, null, 2)}</div>;
10 +}
1 +import { useState, useCallback, useEffect } from "react";
2 +import ky from "ky";
3 +
4 +interface FileListResponse {
5 + data: FileItem & {
6 + list: FileItem[];
7 + };
8 +}
9 +
10 +interface FileItem {
11 + is_folder: boolean;
12 + name: string;
13 + file_type: "folder" | "file";
14 + path: string;
15 + parent: number;
16 + user_id: number;
17 + size: number;
18 + is_deleted: boolean;
19 + created_time: string | null;
20 + updated_time: string;
21 + status: boolean;
22 + id: number;
23 +}
24 +
25 +interface Token {
26 + accessToken: string;
27 + refreshToken: string;
28 + expiration: Date;
29 + user: {
30 + id: number;
31 + username: string;
32 + name: string;
33 + totalSize: number;
34 + currentSize: number;
35 + rootFolder: number;
36 + };
37 +}
38 +
39 +export function useFileList(id: string) {
40 + const [data, setData] = useState<FileListResponse | null>(null);
41 +
42 + const reload = useCallback(async () => {
43 + const response = await ky
44 + .get(`/items/${id}/children/`)
45 + .json<FileListResponse>();
46 +
47 + setData(response);
48 + }, [id]);
49 +
50 + useEffect(() => {
51 + reload();
52 + }, [reload]);
53 +
54 + return { data, reload };
55 +}
1 +import { useRef, useEffect } from "react";
2 +
3 +export function usePrevious<T>(value: T) {
4 + const ref = useRef<T>();
5 + useEffect(() => {
6 + ref.current = value;
7 + });
8 + return ref.current as T;
9 +}