Skip to content

Commit 49e755d

Browse files
committed
rename to PhoneBook and add FavoritesList
1 parent 6c57ad7 commit 49e755d

File tree

12 files changed

+180
-41
lines changed

12 files changed

+180
-41
lines changed

examples/cookbook/app/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,5 @@ type Recipe = {
8484
const recipes: Recipe[] = [
8585
{ id: 1, title: 'Welcome Screen with Custom Render', path: 'custom-render/' },
8686
{ id: 2, title: 'Task List with Jotai', path: 'state-management/jotai/' },
87-
{ id: 3, title: 'Users Home with\na Variety of Net. Req. Methods', path: 'network-requests/' },
87+
{ id: 3, title: 'Phone book with\na Variety of Net. Req. Methods', path: 'network-requests/' },
8888
];
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { User } from './types';
3+
import ContactsList from './components/ContactsList';
4+
import FavoritesList from './components/FavoritesList';
5+
import getAllContacts from './api/getAllContacts';
6+
import getAllFavorites from './api/getAllFavorites';
7+
8+
export default () => {
9+
const [usersData, setUsersData] = useState<User[]>([]);
10+
const [favoritesData, setFavoritesData] = useState<User[]>([]);
11+
useEffect(() => {
12+
const _getAllContacts = async () => {
13+
const _data = await getAllContacts();
14+
setUsersData(_data);
15+
};
16+
const _getAllFavorites = async () => {
17+
const _data = await getAllFavorites();
18+
setFavoritesData(_data);
19+
};
20+
21+
const run = async () => {
22+
await Promise.all([_getAllContacts(), _getAllFavorites()]);
23+
};
24+
25+
void run();
26+
}, []);
27+
28+
return (
29+
<>
30+
<FavoritesList users={favoritesData} />
31+
<ContactsList users={usersData} />
32+
</>
33+
);
34+
};

examples/cookbook/app/network-requests/UsersHome.tsx

Lines changed: 0 additions & 31 deletions
This file was deleted.

examples/cookbook/app/network-requests/__tests__/UsersListFetch.test.tsx renamed to examples/cookbook/app/network-requests/__tests__/PhoneBook.test.tsx

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { render, screen, waitForElementToBeRemoved } from '@testing-library/react-native';
22
import React from 'react';
3-
import UsersHome from '../UsersHome';
3+
import PhoneBook from '../PhoneBook';
44
import { User } from '../types';
55

6+
// Ensure that the global fetch function is mocked in your setup file
7+
// before running the tests. This will ensure that the tests don't
8+
// make any actual network requests that you haven't mocked.
69
beforeAll(() => {
710
jest.spyOn(global, 'fetch').mockImplementation(
811
jest.fn(() => {
@@ -15,18 +18,36 @@ afterAll(() => {
1518
(global.fetch as jest.Mock).mockRestore();
1619
});
1720

18-
describe('UsersListFetch', () => {
19-
it('fetches users successfully and renders in list', async () => {
20-
jest.spyOn(global, 'fetch').mockResolvedValueOnce({
21+
describe('PhoneBook', () => {
22+
let originalFetch: typeof global.fetch;
23+
beforeAll(() => {
24+
originalFetch = global.fetch;
25+
global.fetch = jest.fn().mockResolvedValueOnce({
2126
json: jest.fn().mockResolvedValueOnce(DATA),
22-
} as unknown as Response);
23-
render(<UsersHome />);
27+
});
28+
//TODO: mock axios
29+
});
30+
31+
afterAll(() => {
32+
global.fetch = originalFetch;
33+
});
34+
35+
it('fetches contacts successfully and renders in list', async () => {
36+
render(<PhoneBook />);
2437

2538
await waitForElementToBeRemoved(() => screen.getByText(/users data not quite there yet/i));
2639
expect(await screen.findByText('Name: Mrs Ida Kristensen')).toBeOnTheScreen();
2740
expect(await screen.findByText('Email: [email protected]')).toBeOnTheScreen();
2841
expect(await screen.findAllByText(/name/i)).toHaveLength(3);
2942
});
43+
44+
it('fetches favorites successfully and renders in list', async () => {
45+
render(<PhoneBook />);
46+
47+
await waitForElementToBeRemoved(() => screen.getByText(/figuring out your favorites/i));
48+
expect(await screen.findByText(/my favorites/i)).toBeOnTheScreen();
49+
expect(await screen.findAllByText(/name/i)).toHaveLength(3);
50+
});
3051
});
3152

3253
const DATA: { results: User[] } = {
@@ -47,6 +68,7 @@ const DATA: { results: User[] } = {
4768
medium: 'https://randomuser.me/api/portraits/med/women/26.jpg',
4869
thumbnail: 'https://randomuser.me/api/portraits/thumb/women/26.jpg',
4970
},
71+
cell: '123-4567-890',
5072
},
5173
{
5274
name: {
@@ -64,6 +86,7 @@ const DATA: { results: User[] } = {
6486
medium: 'https://randomuser.me/api/portraits/med/men/53.jpg',
6587
thumbnail: 'https://randomuser.me/api/portraits/thumb/men/53.jpg',
6688
},
89+
cell: '123-4567-890',
6790
},
6891
{
6992
name: {
@@ -81,6 +104,7 @@ const DATA: { results: User[] } = {
81104
medium: 'https://randomuser.me/api/portraits/med/men/17.jpg',
82105
thumbnail: 'https://randomuser.me/api/portraits/thumb/men/17.jpg',
83106
},
107+
cell: '123-4567-890',
84108
},
85109
],
86110
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { User } from '../types';
2+
3+
export default async (): Promise<User[]> => {
4+
const res = await fetch('https://randomuser.me/api/?results=25');
5+
const json = await res.json();
6+
return json.results;
7+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import axios from 'axios';
2+
import { User } from '../types';
3+
4+
export default async (): Promise<User[]> => {
5+
const res = await axios.get('https://randomuser.me/api/?results=10');
6+
return res.data.results;
7+
};

examples/cookbook/app/network-requests/components/UserList.tsx renamed to examples/cookbook/app/network-requests/components/ContactsList.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { User } from '../types';
55

66
export default ({ users }: { users: User[] }) => {
77
const renderItem: ListRenderItem<User> = useCallback(
8-
({ item: { name, email, picture }, index }) => {
8+
({ item: { name, email, picture, cell }, index }) => {
99
const { title, first, last } = name;
1010
const backgroundColor = index % 2 === 0 ? '#f9f9f9' : '#fff';
1111
return (
@@ -16,6 +16,7 @@ export default ({ users }: { users: User[] }) => {
1616
Name: {title} {first} {last}
1717
</Text>
1818
<Text>Email: {email}</Text>
19+
<Text>Mobile: {cell}</Text>
1920
</View>
2021
</View>
2122
);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { FlatList, Image, StyleSheet, Text, View } from 'react-native';
2+
import React, { useCallback } from 'react';
3+
import type { ListRenderItem } from '@react-native/virtualized-lists';
4+
import { User } from '../types';
5+
6+
export default ({ users }: { users: User[] }) => {
7+
const renderItem: ListRenderItem<User> = useCallback(({ item: { picture } }) => {
8+
return (
9+
<View style={styles.userContainer}>
10+
<Image source={{ uri: picture.thumbnail }} style={styles.userImage} />
11+
</View>
12+
);
13+
}, []);
14+
15+
if (users.length === 0) return <FullScreenLoader />;
16+
17+
return (
18+
<View style={styles.outerContainer}>
19+
<Text>⭐My Favorites</Text>
20+
<FlatList<User>
21+
horizontal
22+
showsHorizontalScrollIndicator={false}
23+
data={users}
24+
renderItem={renderItem}
25+
keyExtractor={(item, index) => `${index}-${item.id.value}`}
26+
/>
27+
</View>
28+
);
29+
};
30+
const FullScreenLoader = () => {
31+
return (
32+
<View style={styles.loaderContainer}>
33+
<Text>Figuring out your favorites...</Text>
34+
</View>
35+
);
36+
};
37+
38+
const styles = StyleSheet.create({
39+
outerContainer: {
40+
padding: 8,
41+
},
42+
userContainer: {
43+
padding: 8,
44+
flexDirection: 'row',
45+
alignItems: 'center',
46+
},
47+
userImage: {
48+
width: 52,
49+
height: 52,
50+
borderRadius: 36,
51+
borderColor: '#9b6dff',
52+
borderWidth: 2,
53+
},
54+
loaderContainer: { height: 52, justifyContent: 'center', alignItems: 'center' },
55+
});
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
2-
import UsersHome from './UsersHome';
2+
import PhoneBook from './PhoneBook';
33

44
export default function Example() {
5-
return <UsersHome />;
5+
return <PhoneBook />;
66
}

examples/cookbook/app/network-requests/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ export type User = {
1414
medium: string;
1515
thumbnail: string;
1616
};
17+
cell: string;
1718
};

0 commit comments

Comments
 (0)