Post

ReactNative app #7 : Home (header, category, product list)

Configuration for header

Add folders and files.

1
2
3
4
5
6
7
8
9
10
11
12
Apps
├── Compoents
│   ├── Slider.jsx
│   ├── PostItem.jsx
│   ├── Categories.jsx
│   ├── Header.jsx
│   └── LatestItemList.cs
├── Screens
│   ├── HomeScreen.jsx
│   ├── ExploreScreen.jsx
│   ├── ProfileScreen.jsx
│   └── AddPostScreen.cs

Add dependency folder and file in a tailwind.config.js (to recognize tailwind css in those files)

1
2
3
4
5
6
7
8
9
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./App.{js,jsx,ts,tsx}", "./Apps/**/*.{js,jsx,ts,tsx}", 
					  "./Components/Homescreen/**/*.{js,jsx,ts,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
}

Add a basic code by rnf (reactNativeFunctionalCompoents)

1
2
3
4
5
6
7
8
9
10
import { View, Text } from 'react-native'
import React from 'react'

export default function Header() {
  return (
    <View>
      <Text>Header</Text>
    </View>
  )
}

User information

1
2
3
4
5
6
import { useUser } from '@clerk/clerk-expo'

...

export default function Header() {
    const {user} = useUser();

Show the information on the information section

1
2
3
4
5
6
7
8
9
10
11
12
return (
    <View>
        {/* User infor sectiion */}
        <View className="flex flex-row items-center gap-4">
            <Image source= 
                className="rounded-full w-12 h-12"
            />
            <View>
                <Text className="text-[16px]">Welcome</Text>
                <Text className="text-[20px] font-bold">{user?.fullName}</Text>
            </View>
        </View>

Search input box

1
2
3
4
5
6
7
8
	      {/* Search bar section  */}
	      <View className="p-2 px-5 mt-5 flex flex-row bg-white rounded-full border-[2px] border-blue-300">
	          <EvilIcons name="search" size={24} color="gray" />
	          <TextInput placeholder='Search' 
	              className="ml-2 text-[18px]"
	              onChangeText={(value) => console.log(value)}    
	          />
	      </View>

Include Header component in Homescreen.jsx

1
2
3
  <View className="py-8 px-6 bg-white flex-1">
    <Header />
  </View>

h1

Slider

  • make new collection for images in firestore database

h01

{image:”url”}

Add code in slider component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { View, Text, FlatList, Image } from 'react-native'
import React from 'react'

export default function Slider({sliderList}) {
  return (
    <View className="mt-5">
      <FlatList
        data={sliderList}
        horizontal={true}
        showsHorizontalScrollIndicator={false}
        renderItem={({item,index})=>(
          <View>
            <Image source=
              className="h-[200px] w-[330px] mr-3 rounded-lg object-contain"
              />
          </View>
        )}
        />
    </View>
  )
}
  • Attach Slider at Homescreen
1
2
3
import Slider from '../../Components/Homescreen/Slider'
import {collection, getDocs, getFirestore} from 'firebase/firestore';
import {app} from '../../firebaseConfig';
1
  const db = getFirestore(app); // get firestore database
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// loading slider data
const [sliderList,setSliderList]=useState([]);
useEffect(()=>{
	getSliders();
},[])

const getSliders= async ()=>{
	setSliderList([]);
	const querySnapshot = await getDocs(collection(db, "Sliders"));
	querySnapshot.forEach((doc) => {
	console.log(doc.id, " => ", doc.data());
	setSliderList(sliderList=>[...sliderList,doc.data()]);
	});
}
1
2
3
4
5
6
  return (
      <View className="py-8 px-6 bg-white flex-1">
        <Header />
        <Slider sliderList={sliderList}/>
      </View>
  )

h2

categoryList

homescreen

1
import Categories from '../../Components/Homescreen/Categories';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const [sliderList,setSliderList]=useState([]);
const [categoryList,setCategoryList]=useState([]);
useEffect(()=>{
  getSliders();
  getCategoryList();
},[])

const getCategoryList=async()=>{
  setCategoryList([]);
  const querySnapshot = await getDocs(collection(db, 'Category'));

  querySnapshot.forEach((doc)=> {
      console.log("Docs:", doc.data());
      setCategoryList(categoryList=>[...categoryList,doc.data()]);
  })
  
return (
  <View className="py-8 px-6 bg-white flex-1">
    <Header />
    <Slider sliderList={sliderList}/>
    <Categories categoryList={categoryList}/>
  </View>
)

categories.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { View, Text, FlatList, Image, TouchableOpacity } from 'react-native'
import React from 'react'

export default function Categories({categoryList}) { // {value} should be object
  
  return (
    <View className="mt-3">
      <Text className="font-bold textz-[20px]">Categories</Text>
      <FlatList
        data={categoryList}
        numColumns={4}
        renderItem={({item,index})=>(
          <TouchableOpacity className="flex-1 items-center justify-center p-2 border-[1px] border-gray-300 m-1 h-[80px] rounded-lg">
            <Image source= // source=
             className="w-[40px] h-[40px]"
            />
            <Text className="text-[12px] mt-1">{item.name}</Text>
          </TouchableOpacity>
        )}
        />
    </View>
  )
}

h3

Product list

  • add created time

→ install moment (moment.js.com) to format date

npm install moment - - save

→ add “createdAt” field in AddPostScreen.jsx

1
initialValues=
  • get user post

→ getLatestsItemList

1
2
3
4
5
6
7
8
const getLatestItemList=async()=>{
  setLatestItemList([]);
  const querySnapshot=await getDocs(collection(db, 'UserPost'), orderBy('createdAt', 'desc')); 
  querySnapshot.forEach((doc) => {
    console.log("Docs:", doc.data());
    setLatestItemList(latestItemList=>[...latestItemList,doc.data()]);
  })
}

→ call getLatestItemList

1
2
3
4
5
6
const [latestItemList,setLatestItemList]=useState([]);
useEffect(()=>{
  getSliders();
  getCategoryList();
  getLatestItemList();
},[])

→ call the component

1
2
3
4
5
6
7
8
  return (
      <ScrollView className="py-8 px-6 bg-white flex-1">
        <Header />
        <Slider sliderList={sliderList}/>
        <Categories categoryList={categoryList}/>
        <LatestItemList latestItemList={latestItemList}/>
      </ScrollView>
  )

LatestItemList component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { View, Text, FlatList, Image, TouchableOpacity } from 'react-native'
import React from 'react'
import PostItem from './PostItem'

export default function LatestItemList({latestItemList}) {
  return (
    <View className="mt-3">
      <Text className="font-bold text-[20px]">Latest Items</Text>
      <FlatList
        data={latestItemList}
        numColumns={2}
        renderItem={({item,index})=>(
          <PostItem item={item} />
        )}
        />
    </View>
  )
}

PostItem (reusable component)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { View, Text, TouchableOpacity, Image} from 'react-native'
import React from 'react'

export default function PostItem({item}) {
  return (
    <TouchableOpacity className="flex-1 m-2 p-2 rounded-lg border-[1px] border-slate-200">
        <Image source= 
        className="w-full h-[140px] rounded-lg "
        />
        <View>
            <Text className="text-[15px] font-bold mt-2">{item.title}</Text>
            <Text className="text-[20px] font-bold text-blue-500">$ {item.price}</Text>
            <Text className="text-blue-500 bg-blue-200 mt-1 p-1 text-center rounded-full px-1 text-[10px] w-[70px]">{item.category}</Text>
        </View>
    </TouchableOpacity>
  )
}

h4

This post is licensed under CC BY 4.0 by the author.