1- import { Outlet , Link , useLoaderData } from " react-router-dom" ;
2- import { getContacts } from " ../contacts" ;
1+ import { Outlet , NavLink , useLoaderData , Form } from ' react-router-dom' ;
2+ import { getContacts , createContact } from ' ../contacts' ;
33
4- export async function loader ( ) {
5- const contacts = await getContacts ( ) ;
6- return { contacts } ;
7- }
4+ export const loader = async ( ) => {
5+ const contacts = await getContacts ( ) ;
6+ return { contacts } ;
7+ } ;
8+
9+ export const action = async ( ) => {
10+ const contact = await createContact ( ) ;
11+ return { contact } ;
12+ } ;
813
914export default function Root ( ) {
10- const { contacts} = useLoaderData ( )
11- return (
12- < >
13- < div id = "sidebar" >
14- < h1 > React Router Contacts</ h1 >
15- < div >
16- < form id = "search-form" role = "search" >
17- < input
18- id = "q"
19- aria-label = "Search contacts"
20- placeholder = "Search"
21- type = "search"
22- name = "q"
23- />
24- < div
25- id = "search-spinner"
26- aria-hidden
27- hidden = { true }
28- />
29- < div
30- className = "sr-only"
31- aria-live = "polite"
32- > </ div >
33- </ form >
34- < form method = "post" >
35- < button type = "submit" > New</ button >
36- </ form >
37- </ div >
38- { contacts . length ? (
39- < ul >
40- { contacts . map ( ( contact ) => (
41- < li key = { contact . id } >
42- < Link to = { `contacts/${ contact . id } ` } >
43- { contact . first || contact . last ? (
44- < >
45- { contact . first } { contact . last }
46- </ >
47- ) : (
48- < i > No Name</ i >
49- ) } { " " }
50- { contact . favorite && < span > ★</ span > }
51- </ Link >
52- </ li >
53- ) ) }
54- </ ul >
55- ) : (
56- < p >
57- < i > No contacts</ i >
58- </ p >
59- ) }
60- </ div >
61- < div id = "detail" >
62- < Outlet />
63- </ div >
64- </ >
65- ) ;
66- }
15+ const { contacts } = useLoaderData ( ) ;
16+ return (
17+ < >
18+ < div id = 'sidebar' >
19+ < h1 > React Router Contacts</ h1 >
20+ < div >
21+ < form id = 'search-form' role = 'search' >
22+ < input
23+ id = 'q'
24+ aria-label = 'Search contacts'
25+ placeholder = 'Search'
26+ type = 'search'
27+ name = 'q'
28+ />
29+ < div id = 'search-spinner' aria-hidden hidden = { true } />
30+ < div className = 'sr-only' aria-live = 'polite' > </ div >
31+ </ form >
32+ < Form method = 'post' >
33+ < button type = 'submit' > New</ button >
34+ </ Form >
35+ </ div >
36+ { contacts . length ? (
37+ < ul >
38+ { contacts . map ( ( contact ) => (
39+ < li key = { contact . id } >
40+ < NavLink
41+ to = { `contacts/${ contact . id } ` }
42+ className = { ( { isActive, isPending } ) =>
43+ isActive ? 'active' : isPending ? 'peding' : ''
44+ }
45+ >
46+ { contact . first || contact . last ? (
47+ < >
48+ { contact . first } { contact . last }
49+ </ >
50+ ) : (
51+ < i > No Name</ i >
52+ ) } { ' ' }
53+ { contact . favorite && < span > ★</ span > }
54+ </ NavLink >
55+ </ li >
56+ ) ) }
57+ </ ul >
58+ ) : (
59+ < p >
60+ < i > No contacts</ i >
61+ </ p >
62+ ) }
63+ </ div >
64+ < div id = 'detail' >
65+ < Outlet />
66+ </ div >
67+ </ >
68+ ) ;
69+ }
0 commit comments