Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 19c2526

Browse filesBrowse files
committed
Chapter 20
1 parent 2f7b150 commit 19c2526
Copy full SHA for 19c2526

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

62 files changed

+54885
-0
lines changed
+35Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
2+
3+
# dependencies
4+
node_modules/
5+
6+
# Expo
7+
.expo/
8+
dist/
9+
web-build/
10+
11+
# Native
12+
*.orig.*
13+
*.jks
14+
*.p8
15+
*.p12
16+
*.key
17+
*.mobileprovision
18+
19+
# Metro
20+
.metro-health-check*
21+
22+
# debug
23+
npm-debug.*
24+
yarn-debug.*
25+
yarn-error.*
26+
27+
# macOS
28+
.DS_Store
29+
*.pem
30+
31+
# local env files
32+
.env*.local
33+
34+
# typescript
35+
*.tsbuildinfo

‎Chapter20/fetching-list-data/App.tsx

Copy file name to clipboard
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from "react";
2+
import { View } from "react-native";
3+
import styles from "./styles";
4+
import ListContainer from "./ListContainer";
5+
6+
export default function App() {
7+
return (
8+
<View style={styles.container}>
9+
<ListContainer />
10+
</View>
11+
);
12+
}

‎Chapter20/fetching-list-data/List.tsx

Copy file name to clipboard
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React from "react";
2+
import { Text, FlatList } from "react-native";
3+
import styles from "./styles";
4+
import ListControls from "./ListControls";
5+
6+
type Props = {
7+
data: { key: string; value: string }[];
8+
onFilter: (value: string) => void;
9+
onSort: () => void;
10+
asc: boolean;
11+
};
12+
13+
export default function List({ data, onFilter, onSort, asc }: Props) {
14+
return (
15+
<FlatList
16+
data={data}
17+
ListHeaderComponent={<ListControls {...{ onFilter, onSort, asc }} />}
18+
renderItem={({ item }) => <Text style={styles.item}>{item.value}</Text>}
19+
/>
20+
);
21+
}
+46Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React, { useState, useEffect } from "react";
2+
import { fetchItems } from "./api";
3+
import List from "./List";
4+
5+
type MappedList = { key: string; value: string }[];
6+
7+
function mapItems(items: string[]): MappedList {
8+
return items.map((value, i) => ({ key: i.toString(), value }));
9+
}
10+
11+
export default function ListContainer() {
12+
const [asc, setAsc] = useState(true);
13+
const [filter, setFilter] = useState("");
14+
const [data, setData] = useState<MappedList>([]);
15+
16+
useEffect(() => {
17+
fetchItems(filter, asc)
18+
.then((resp) => resp.json())
19+
.then(({ items }) => {
20+
setData(mapItems(items));
21+
});
22+
}, []);
23+
24+
return (
25+
<List
26+
data={data}
27+
asc={asc}
28+
onFilter={(text) => {
29+
fetchItems(text, asc)
30+
.then((resp) => resp.json())
31+
.then(({ items }) => {
32+
setFilter(text);
33+
setData(mapItems(items));
34+
});
35+
}}
36+
onSort={() => {
37+
fetchItems(filter, !asc)
38+
.then((resp) => resp.json())
39+
.then(({ items }) => {
40+
setAsc(!asc);
41+
setData(mapItems(items));
42+
});
43+
}}
44+
/>
45+
);
46+
}
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from "react";
2+
import { View } from "react-native";
3+
import styles from "./styles";
4+
import ListFilter from "./ListFilter";
5+
import ListSort from "./ListSort";
6+
7+
type Props = {
8+
onFilter: (value: string) => void;
9+
onSort: () => void;
10+
asc: boolean;
11+
};
12+
13+
export default function ListControls({ onFilter, onSort, asc }: Props) {
14+
return (
15+
<View style={styles.controls}>
16+
<ListFilter onFilter={onFilter} />
17+
<ListSort onSort={onSort} asc={asc} />
18+
</View>
19+
);
20+
}
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from "react";
2+
import { View, TextInput } from "react-native";
3+
import styles from "./styles";
4+
5+
type Props = {
6+
onFilter: (value: string) => void;
7+
};
8+
9+
export default function ListFilter({ onFilter }: Props) {
10+
return (
11+
<View>
12+
<TextInput
13+
autoFocus
14+
placeholder="Search"
15+
style={styles.filter}
16+
onChangeText={onFilter}
17+
/>
18+
</View>
19+
);
20+
}
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from "react";
2+
import PropTypes from "prop-types";
3+
import { Text } from "react-native";
4+
5+
const arrows = new Map([
6+
[true, "▼"],
7+
[false, "▲"],
8+
]);
9+
10+
type Props = {
11+
onSort: () => void;
12+
asc: boolean;
13+
};
14+
15+
export default function ListSort({ onSort, asc }: Props) {
16+
return <Text onPress={onSort}>{arrows.get(asc)}</Text>;
17+
}
18+
19+
ListSort.propTypes = {
20+
onSort: PropTypes.func.isRequired,
21+
asc: PropTypes.bool.isRequired,
22+
};

‎Chapter20/fetching-list-data/api.ts

Copy file name to clipboard
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const items = new Array(100).fill(null).map((v, i) => `Item ${i}`);
2+
3+
function filterAndSort(data: string[], text: string, asc: boolean) {
4+
return data
5+
.filter((i) => text.length === 0 || i.includes(text))
6+
.sort(
7+
asc
8+
? (a, b) => (b > a ? -1 : a === b ? 0 : 1)
9+
: (a, b) => (a > b ? -1 : a === b ? 0 : 1)
10+
);
11+
}
12+
13+
export function fetchItems(
14+
filter: string,
15+
asc: boolean
16+
): Promise<{ json: () => Promise<{ items: string[] }> }> {
17+
return new Promise((resolve) => {
18+
resolve({
19+
json: () =>
20+
Promise.resolve({
21+
items: filterAndSort(items, filter, asc),
22+
}),
23+
});
24+
});
25+
}

‎Chapter20/fetching-list-data/app.json

Copy file name to clipboard
+30Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"expo": {
3+
"name": "fetching-list-data",
4+
"slug": "fetching-list-data",
5+
"version": "1.0.0",
6+
"orientation": "portrait",
7+
"icon": "./assets/icon.png",
8+
"userInterfaceStyle": "light",
9+
"splash": {
10+
"image": "./assets/splash.png",
11+
"resizeMode": "contain",
12+
"backgroundColor": "#ffffff"
13+
},
14+
"assetBundlePatterns": [
15+
"**/*"
16+
],
17+
"ios": {
18+
"supportsTablet": true
19+
},
20+
"android": {
21+
"adaptiveIcon": {
22+
"foregroundImage": "./assets/adaptive-icon.png",
23+
"backgroundColor": "#ffffff"
24+
}
25+
},
26+
"web": {
27+
"favicon": "./assets/favicon.png"
28+
}
29+
}
30+
}
Loading
1.43 KB
Loading
21.9 KB
Loading
46.2 KB
Loading
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = function(api) {
2+
api.cache(true);
3+
return {
4+
presets: ['babel-preset-expo'],
5+
};
6+
};

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.