I am trying to add pagination function for the web in React Native. Essentially I have two issues.
I have linked the data to the page numbers, so it is calculating the number of pages correctly, but the pages don't change when I hit the arrow to the next page.
The page selection dropdown doesn't work. I can change the number in the code to show a specific number of items on the page, but not through the dropdown on the page.
Page Numbers changing when I manually change how many to display per page
I've included some of the code below that relates to this.
import React, { useEffect, useState } from 'react';
import { StyleSheet, ActivityIndicator, Text, View, FlatList, Modal, Dimensions } from 'react-native';
import Moment from 'react-moment';
import { DataTable } from 'react-native-paper';
import { AntDesign } from '#expo/vector-icons';
import TaskView from '../components/TaskView';
import { Switch } from 'react-native-paper';
import DropDownPicker from 'react-native-dropdown-picker'
import { RFValue } from "react-native-responsive-fontsize";
const window = Dimensions.get("window");
const screen = Dimensions.get("screen");
const numberOfItemsPerPageList = [1, 5, 10, 25, 50, 100];
function TaskList(props) {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [modalVisible, setModalVisible] = useState(false);
const [dimensions, setDimensions] = useState({ window, screen });
const [id, setId] = useState('');
const moment = require('moment');
const [toggle, setToggle] = useState(false);
const [items, setItems] = useState([]);
const [value, setValue] = useState([]);
const [open, setOpen] = useState(false);
const [page, setPage] = useState(1);
const [numberOfItemsPerPage, onItemsPerPageChange] = useState(numberOfItemsPerPageList[1]);
const [currentPage, setCurrentPage] = useState(1);
const indexOfLastItem = currentPage * numberOfItemsPerPage;
const indexOfFirstItem = indexOfLastItem - numberOfItemsPerPage;
const currentItems = dataSet.slice(indexOfFirstItem, indexOfLastItem);
const dataLength = filteredData.length;
const totalPages = Math.ceil(dataLength / numberOfItemsPerPage);
return (
<View style={styles.mainContainer}>
<View style={styles.switchContainer}>
<Text style={styles.switchText}>Future Defer Dates:</Text>
<Switch value={toggle} onValueChange={toggleSwitch} />
</View>
<DropDownPicker
placeholder='Filter'
items={items}
open={open}
setOpen={setOpen}
value={value}
setValue={setValue}
multiple={true}
mode='BADGE'
badgeDotColors={["blue", "green", "red", "orange", "pink", "yellow", "brown", "violet"]}
onClose={filterData}
/>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
setModalVisible(!modalVisible);
}}
>
<View style={styles.modal}>
<View style={styles.closeCircle}>
<AntDesign name="closecircleo" size={26} color="black" onPress={() => setModalVisible(false)} />
</View>
<TaskView task={id} />
</View>
</Modal>
<DataTable>
**<DataTable.Pagination
page={page}
// onClick={}
totalItems={dataLength}
numberOfPages={totalPages}
onPageChange={page => setCurrentPage(currentPage+1)}
selectPageDropdown={numberOfItemsPerPageList}
label={`${currentPage} of ${totalPages} pages`} //text # of # pages
selectPageDropdownLabel={'Tasks per page'} //text next to task amount number drop down
numberOfItemsPerPageList={numberOfItemsPerPageList} //task amount number drop down
showFastPaginationControls //arrows to the first and last page
numberOfItemsPerPage={numberOfItemsPerPage}
onItemsPerPageChange={onItemsPerPageChange}
/>**
<DataTable.Header style={{ position: 'sticky', top: '0px', backgroundColor: "#eaeaea", zIndex: 1 }}>
<DataTable.Title><Text style={{ fontSize: 30, fontWeight: 'bold', position: 'absolute', color: 'black' }}>Task</Text></DataTable.Title>
<DataTable.Title><Text style={{ fontSize: 30, fontWeight: 'bold', position: 'absolute', color: 'black' }}>Due Date</Text></DataTable.Title>
<DataTable.Title><Text style={{ fontSize: 30, fontWeight: 'bold', position: 'absolute', color: 'black' }}>Status</Text></DataTable.Title>
<DataTable.Title><Text style={{ fontSize: 30, fontWeight: 'bold', position: 'absolute', color: 'black' }}>Category</Text></DataTable.Title>
</DataTable.Header>
{isLoading ? <ActivityIndicator /> : (
<FlatList
data={filterData()}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<DataTable.Row onPress={() => showModal(item.id)}>
<DataTable.Cell>
<AntDesign name="rightsquare" size={14} color="black" style={{ marginRight: 15 }} />
{item.name}
</DataTable.Cell>
<DataTable.Cell>
<Moment format="MMMM Do YYYY">{item.due_date}</Moment>
</DataTable.Cell>
<DataTable.Cell>
{item.status.status}
</DataTable.Cell>
<DataTable.Cell>
{item.category.name}
</DataTable.Cell>
</DataTable.Row>
)
}
/>
)}
</DataTable>
</View>
);
};
/>
Related
Console Warning
Function components cannot be given refs. Attempts
to access this ref will fail. Did you mean to use
React.forwardRef()?
Check the render method of 'OnboardingScreen'
Warning: Function components cannot be given refs.
Attempts to access this ref will fail. Did you mean to
use React.forwardRef()?%s%S
Check the render method of 'OnboardingScreen*
I get this warning and I can't transmit Ref
OnboardingScreen
import React, {useRef, useState} from 'react';
import {Dimensions, View} from 'react-native';
import {ONBOARDING} from '../data/onboarding';
import Onboarding from '../components/ Onboarding/Onboarding';
import OnboardingFooter from '../components/ Onboarding/OnboardingFooter';
import {colors} from '../constants/config';
const windowWidth = Dimensions.get('window').width;
const OnboardingScreen = () => {
const [currentSate, setCurrentState] = useState(0);
const ref = useRef(null);
const updateCurrentState = e => {
const contentOffsetX = e.nativeEvent.contentOffset.x;
const currentSate = Math.round(contentOffsetX / windowWidth);
setCurrentState(currentSate);
};
const nextSlider = () => {
const nextSliderState = currentSate + 1;
if (nextSliderState != ONBOARDING.length) {
const offset = nextSliderState * windowWidth;
ref?.current?.scrollToOffset({offset});
setCurrentState(nextSliderState);
}
};
return (
<View style={{flex: 1, backgroundColor: colors.lightGray}}>
<Onboarding
list={ONBOARDING}
updateCurrentState={updateCurrentState}
ref={ref}
/>
<OnboardingFooter
list={ONBOARDING}
currentSate={currentSate}
nextSlider={nextSlider}
/>
</View>
);
};
export default OnboardingScreen;
Onboarding
import React from 'react';
import {Dimensions, FlatList, Image, Text, View} from 'react-native';
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;
const Onboarding = ({list, updateCurrentState, ref}) => {
return (
<FlatList
data={list}
horizontal
ref={ref}
pagingEnabled
onMomentumScrollEnd={updateCurrentState}
contentContainerStyle={{height: windowHeight * 0.75}}
showsHorizontalScrollIndicator={false}
renderItem={({item, index}) => {
return (
<View style={{alignItems: 'center'}}>
<Image
source={item.image}
style={{height: '75%', width: windowWidth}}
/>
<Text
style={{
color: 'white',
fontSize: 22,
fontWeight: 'bold',
marginTop: 30,
}}>
{item.title}
</Text>
<Text
style={{
color: 'white',
fontSize: 13,
marginTop: 5,
maxWidth: '80%',
textAlign: 'center',
lineHeight: 23,
}}>
{item.subtitle}
</Text>
</View>
);
}}
/>
);
};
export default Onboarding;
You need to follow forwarding ref concept, refer to this doc: https://reactjs.org/docs/forwarding-refs.html
Your solution is as below:
import React, {useRef, useState} from 'react';
import {Dimensions, View} from 'react-native';
import {ONBOARDING} from '../data/onboarding';
import Onboarding from '../components/ Onboarding/Onboarding';
import OnboardingFooter from '../components/ Onboarding/OnboardingFooter';
import {colors} from '../constants/config';
const windowWidth = Dimensions.get('window').width;
const OnboardingScreen = () => {
const [currentSate, setCurrentState] = useState(0);
const ref = React.createRef(null); //<-----------change here
const updateCurrentState = e => {
const contentOffsetX = e.nativeEvent.contentOffset.x;
const currentSate = Math.round(contentOffsetX / windowWidth);
setCurrentState(currentSate);
};
const nextSlider = () => {
const nextSliderState = currentSate + 1;
if (nextSliderState != ONBOARDING.length) {
const offset = nextSliderState * windowWidth;
ref?.current?.scrollToOffset({offset});
setCurrentState(nextSliderState);
}
};
return (
<View style={{flex: 1, backgroundColor: colors.lightGray}}>
<Onboarding
list={ONBOARDING}
updateCurrentState={updateCurrentState}
ref={ref}
/>
<OnboardingFooter
list={ONBOARDING}
currentSate={currentSate}
nextSlider={nextSlider}
/>
</View>
);
};
export default OnboardingScreen;
Onboarding
import React from 'react';
import {Dimensions, FlatList, Image, Text, View} from 'react-native';
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;
const Onboarding = React.forwardRef(({list, updateCurrentState},ref) => { //<====================here
return (
<FlatList
data={list}
horizontal
ref={ref}
pagingEnabled
onMomentumScrollEnd={updateCurrentState}
contentContainerStyle={{height: windowHeight * 0.75}}
showsHorizontalScrollIndicator={false}
renderItem={({item, index}) => {
return (
<View style={{alignItems: 'center'}}>
<Image
source={item.image}
style={{height: '75%', width: windowWidth}}
/>
<Text
style={{
color: 'white',
fontSize: 22,
fontWeight: 'bold',
marginTop: 30,
}}>
{item.title}
</Text>
<Text
style={{
color: 'white',
fontSize: 13,
marginTop: 5,
maxWidth: '80%',
textAlign: 'center',
lineHeight: 23,
}}>
{item.subtitle}
</Text>
</View>
);
}}
/>
);
}); //<============here
export default Onboarding;
In ReactNative, the bottomsheet is displayed overlaid on the fragment.
Is there a way to make the bottomsheet rise to the top of the screenenter image description here
The bottom sheet looks opaque as in the picture, so the bottom sheet cannot be touched Please help
The code below is a shortened version
enter image description here
enter image description here
import React, { FC , Component, useState, useEffect, Fragment,useCallback, useMemo, useRef } from "react"
import { FlatList, ViewStyle, StyleSheet, View, Platform, TextInput, TouchableOpacity} from "react-native"
import {
BottomSheetModal,
BottomSheetModalProvider,
BottomSheetBackdrop,
} from '#gorhom/bottom-sheet';
const ROOT: ViewStyle = {
backgroundColor: DefaultTheme.colors.background,
flex: 1,
}
export const ChecklookupScreen: FC<StackScreenProps<NavigatorParamList, "checklookup">> = observer(function ChecklookupScreen() {
const bottomSheetModalRef = useRef<BottomSheetModal>(null);
// variables
const snapPoints = useMemo(() => ['25%', '50%'], []);
// callbacks
const handlePresentModalPress = useCallback((index: string) => {
LOG.info('handlePresentModalPress', index);
bottomSheetModalRef.current?.present();
}, []);
const handleSheetChanges = useCallback((index: number) => {
LOG.info
console.log('handleSheetChanges', index);
}, []);
const renderItem = ({ item, index }) => (
<TouchableOpacity
key={index + item.inspNo + item.spvsNo}
//style={listContainer}
onPress={throttle(() => {
onClickItem(item.inspNo,item.spvsNo);
})}
>
<View>
<Fragment>
</View>
<Button icon="magnify-expand"
mode="elevated"
style={styles.detailButton}
onPress={throttle(() => {
onClickItem(item.inspNo,item.spvsNo);
})}
// onPress={() => navigation.navigate("checkdetail")}
>
</Button>
</View>
</Fragment>
</View>
</TouchableOpacity>
);
const fetchChecklookups = async (offset: number) => {
LOG.debug('fetchChecklookups:' + offset);
setRefreshing(true);
await checklookupStore.getChecklookups(offset)
setRefreshing(false);
};
const onEndReached = () => {
if (checklookupStore?.checklookupsTotalRecord <= checklookups?.length) {
LOG.debug('onEndReached555555555');
} else {
setPage(page + 1)
fetchChecklookups(page + 1);
}
};
const [searchQuery, setSearchQuery] = React.useState('');
const onChangeSearch = query => setSearchQuery(query);
return (
<Screen preset="fixed" style={{ backgroundColor: colors.background, flex: 1, padding: 10,}}>
<View style={{ flex: 1,}}>
<View style={{ flex: 1, }}>
<Searchbar
placeholder="조회조건을 입력해주세요"
onChangeText={onChangeSearch}
value={searchQuery}
onPressIn={() => handlePresentModalPress('touch on')}
/>
<BottomSheetModalProvider>
<BottomSheetModal
backgroundStyle={{ backgroundColor: "gray" }}
style={styles.bottomSheet}
ref={bottomSheetModalRef}
index={1}
snapPoints={snapPoints}
onChange={handleSheetChanges}
>
<View style={{ marginTop: 10, marginLeft: 50, marginRight: 50, flexDirection: "row"}}>
<View style={{ flex: 1, }}>
<Button
mode="outlined"
>소속을 입력하세요
</Button>
</View>
</View>
</BottomSheetModal>
</BottomSheetModalProvider>
</Screen>
)
})
You can try with portal, wrap you bottom sheet to from another package.
I am trying to make a ticket app that allows for people to create tickets based on work that needs done. Right now, I need help with the expandable view for each ticket card. What I'm wanting is when a user presses on a specific card, it will expand the view and provide more details for only that card. What it is currently doing is expanding the view for every ticket card in the list. I'm new to React Native and trying my best, but nothing has worked so far.
Here is my parent which is called Home:
import React, {useState, useEffect} from 'react';
import {styles, Colors} from '../components/styles';
import { SafeAreaView } from 'react-native';
import Ticket from '../components/Ticket';
const data = [
{
name: 'Josh Groban',
subject: 'U-Joint',
desc: 'The bolt that is meant to hold the u-joint in place has the head broken off from it. See attached picture.',
assignee: 'John Doe',
assigneeConfirmedComplete: 'NA',
dateReported: 'Tue Mar 8, 2022',
vehicle: 'Truck 1',
media: '',
key: '1',
isShowing: false
},
// code removed for brevity
];
const Home = ({navigation}) => {
const [ticketList, setTicketList] = useState(data);
const getTickets = () => {
setTicketList(data);
}
useEffect(() => {
getTickets();
}, []);
return (
<SafeAreaView style={styles.HomeContainer}>
<Ticket
ticketList={ticketList}
setTicketList={setTicketList}
/>
</SafeAreaView>
)
};
export default Home;
And here is the main component that has all of the ticket card configurations:
import React, {useState, useEffect} from 'react';
import {Text, FlatList, View, SafeAreaView, Button, Image, TouchableOpacity } from 'react-native';
import {styles, Colors} from './styles';
import {Ionicons} from '#expo/vector-icons';
const Ticket = ({ticketList, setTicketList}) => {
const defaultImage = 'https://airbnb-clone-prexel-images.s3.amazonaws.com/genericAvatar.png';
const [isComplete, setIsComplete] = useState(false);
const [show, setShow] = useState(false);
const showContent = (data) => {
const isShowing = {...data, isShowing}
if (isShowing)
setShow(!show);
}
const completeTask = () => {
setIsComplete(!isComplete);
}
return (
<SafeAreaView style={{flex: 1}}>
<FlatList showsVerticalScrollIndicator={false}
data={ticketList}
renderItem={(data) => {
return (
<>
<TouchableOpacity key={data.item.key} onPress={() => showContent(data.item.isShowing = true)}>
<View style={styles.TicketCard}>
<Image
style={styles.TicketCardImage}
source={{uri: defaultImage}}
/>
<View style={styles.TicketCardInner}>
<Text style={styles.TicketCardName}>{data.item.vehicle}</Text>
<Text style={styles.TicketCardSubject}>
{data.item.subject}
</Text>
</View>
<TouchableOpacity>
<Ionicons
name='ellipsis-horizontal-circle'
color={Colors.brand}
size={50}
style={styles.TicketCardImage}
/>
</TouchableOpacity>
<TouchableOpacity onPress={completeTask}>
<Ionicons
name={isComplete ? 'checkbox-outline' : 'square-outline'}
color={Colors.brand}
size={50}
style={styles.TicketCardButton}
/>
</TouchableOpacity>
</View>
<View style={styles.TicketCardExpand}>
<Text>
{show &&
(<View style={{padding: 10}}>
<Text style={styles.TicketCardDesc}>
{data.item.desc}
</Text>
<Text style={{padding: 5}}>
Reported by: {data.item.name}
</Text>
<Text style={{padding: 5}}>
Reported: {data.item.dateReported}
</Text>
{isComplete && (
<Text style={{padding: 5}}>
Confirmed Completion: {data.item.assigneeConfirmedComplete}
</Text>
)}
</View>
)}
</Text>
</View>
</TouchableOpacity>
</>
)}}
/>
</SafeAreaView>
)
};
export default Ticket;
Lastly, here are the styles that i'm using:
import {StyleSheet } from "react-native";
import { backgroundColor } from "react-native/Libraries/Components/View/ReactNativeStyleAttributes";
// colors
export const Colors = {
bg: '#eee',
primary: '#fff',
secondary: '#e5e7eb',
tertiary: '#1f2937',
darkLight: '#9ca3f9',
brand: '#1d48f9',
green: '#10b981',
red: '#ff2222',
black: '#000',
dark: '#222',
darkFont: '#bbb',
gray: '#888'
}
export const styles = StyleSheet.create({
HomeContainer: {
flex: 1,
paddingBottom: 0,
backgroundColor: Colors.bg,
},
TicketCard : {
padding: 10,
justifyContent: 'space-between',
borderColor: Colors.red,
backgroundColor: Colors.primary,
marginTop: 15,
flexDirection: 'row',
},
TicketCardExpand: {
justifyContent: 'space-between',
backgroundColor: Colors.primary,
},
TicketCardImage: {
width: 60,
height: 60,
borderRadius: 30
},
TicketCardName:{
fontSize: 17,
fontWeight: 'bold'
},
TicketCardSubject: {
fontSize: 16,
paddingBottom: 5
},
TicketCardDesc: {
fontSize: 14,
flexWrap: 'wrap',
},
TicketCardInner: {
flexDirection: "column",
width: 100
},
TicketCardButton: {
height: 50,
}
});
Any help is greatly appreciated!
Create a Ticket component with its own useState.
const Ticket = (data) => {
const [isOpen, setIsOpen] = useState(false);
const handlePress = () => {
setIsOpen(!isOpen);
}
return (
<TouchableOpacity
onPress={handlePress}
>
// data.item if you use a list, otherwise just data
<YourBasicInformation data={data.item} />
{isOpen && <YourDetailedInformation data={data.item} />}
</TouchableOpacity>
)
}
Render one Ticket for every dataset you have.
<List
style={styles.list}
data={yourDataArray}
renderItem={Ticket}
/>
If you don't want to use a List, map will do the job.
{yourDataArray.map((data) => <Ticket data={data} />)}
instead of setting show to true or false you can set it to something unique to each card like
setShow(card.key or card.id or smth)
and then you can conditionally render details based on that like
{show == card.key && <CardDetails>}
or you can make an array to keep track of open cards
setShow([...show,card.id])
{show.includes(card.id) && <CardDetails>}
//to remove
setShow(show.filter((id)=>id!=card.id))
How do I handle multiple text inputs with only one onChange on React Native?
For example:
Name, age, nationality, eye color.
Additionally, how do I save all of the inputs with only one button? (I want to output a list with all of these inputs in the same "item")
Here's my code with what I did so far, I want to make a sort of movie diary where the user can register new movies they want to watch: (I'm a total beginner btw, so I'm not sure about how to do most things. I'm doing this project to learn)
import React, { useState } from 'react';
import { Button, StyleSheet, View, Text, TextInput, ScrollView } from 'react-native';
import AsyncStorage from '#react-native-async-storage/async-storage';
const Registration = props => {
const [enteredMovieName, setMovieName] = useState("");
const [enteredSynopsis, setSynopsis] = useState("");
const [enteredComments, setComments] = useState("");
const [enteredSource, setSource] = useState("");
const movieData = {
Name: enteredMovieName,
Synopsis: enteredSynopsis,
Comments: enteredComments,
Source: enteredSource,
};
const movieDataHandler = () => {
console.log(movieData);
};
return (
<ScrollView>
<View>
<View>
<Text style={styles.bodyHighlight}>Add new movie</Text>
</View>
<ScrollView>
<View>
<Text style={styles.addMovie} >Movie name:</Text>
<TextInput
placeholder='Cool Movie Name'
style={styles.inputContainer}
onChangeText={enteredText => setMovieName(enteredText)}
value={enteredMovieName}
/>
<Text style={styles.addMovie} >Sinopsis:</Text>
<TextInput
placeholder='Amazing Synopsis'
style={styles.inputContainer}
onChangeText={enteredText => setSynopsis(enteredText)}
value={enteredSynopsis}
/>
<Text style={styles.addMovie} >Comments (optional):</Text>
<TextInput
placeholder='Awesome Thoughts'
style={styles.inputContainer}
onChangeText={enteredText => setComments(enteredText)}
value={enteredComments}
/>
<Text style={styles.addMovie} >Where to watch (optional):</Text>
<TextInput
placeholder='Super Useful Link'
style={styles.inputContainer}
onChangeText={enteredText => setSource(enteredText)}
value={enteredSource}
/>
</View>
<View>
<Button
style={styles.addMovie}
title='ADD'
color='#a30b00'
onPress={movieDataHandler}
/>
<Button
style={styles.addMovie}
title='SEE COMPLETE LIST'
color='#cd5c5c'
onPress={() => {
props.navigation.navigate('Items Screen');
}}
/>
</View>
</ScrollView>
</View >
</ScrollView>
)
}
const styles = StyleSheet.create({
bodyHighlight: {
padding: 10,
margin: 5,
fontWeight: 'bold',
fontSize: 25,
textAlign: 'center',
backgroundColor: '#C4BDBA'
},
inputContainer: {
borderColor: 'black',
borderWidth: 2,
width: 380,
justifyContent: 'center',
alignItems: 'center',
marginHorizontal: 10,
marginBottom: 5,
},
addMovie: {
padding: 10,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'stretch',
marginHorizontal: 10,
},
})
export default Registration;
You can manage all states in an object. For example:
import React from 'react';
import {
SafeAreaView,
StyleSheet,
TextInput,
Button,
Alert,
} from 'react-native';
const UselessTextInput = () => {
const [user, setUserData] = React.useState({ name: '', age: 0 });
return (
<SafeAreaView>
<TextInput
style={styles.input}
onChangeText={(text) => setUserData({...user, name: text })}
value={user.name}
/>
<TextInput
style={styles.input}
onChangeText={(age) => setUserData({...user, age: age })}
value={user.age}
/>
<Button onPress={() => Alert.alert(`User name ${user.name}, age ${user.age}`)} title="click me" />
</SafeAreaView>
);
};
const styles = StyleSheet.create({
input: {
height: 40,
marginTop: 42,
borderWidth: 1,
padding: 10,
},
});
export default UselessTextInput;
create a new function and make changes to the a copied object and push the new object to the state
const handleChange=(key,value)=>{
const myState = user
myState[key] = value
setUserData(myState)
}
then pass the function call to onChangeText prop
<TextInput
style={styles.input}
onChangeText={(text) => handleChange('name', text)}
value={user.name}
/>
I am trying to search items in a flatlist, whenever i type in the search bar it only take one letter and closes the keyboard and the value inside the search bar disappear,
example when i type "george" it only takes the letter g and re-render a list of names containing the letter g and delete what's inside the search bar
how can i fix this ?
import React, { useState, useEffect } from 'react';
import { ScrollView } from 'react-native';
import { View, Text, FlatList, ActivityIndicator, SafeAreaView, TouchableOpacity } from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { Divider, SearchBar } from 'react-native-elements'
const Item = ({ name, lastName }) => (
<View>
<Text style={{ fontSize: 17, color: '#666', marginBottom: 10 }}>Full name: {name} {lastName}</Text>
</View>);
function Clients({ navigation }) {
const [isLoading, setLoading] = useState(true);
const usersApi = 'https://reqres.in/api/users'
const [users, setUsers] = useState([]);
const [search, setSearch] = useState("");
const [masterData, setMasterData] = useState("");
const fetchJson = async (userApi) => {
const response = await fetch(userApi);
return response.json()
}
useEffect(() => {
fetchJson(usersApi)
.then((users) => {
setUsers(users.data);
setMasterData(users.data);
})
.catch((error) => (alert(error)))
.finally(() => setLoading(false));
}, []);
const itemSeparator = () => {
return (
<Divider style={{ width: "105%", marginVertical: 3, alignSelf: 'center' }} />
)
}
const renderHeader = () => {
return (
<SearchBar
placeholder="Type Here..."
lightTheme
round
onChangeText={text => searchFilterFunction(text)}
autoCorrect={false}
/>
);
};
const searchFilterFunction = text => {
setSearch(text);
const newData = masterData.filter(item => {
const itemData = `${item.first_name.toUpperCase()} ${item.last_name.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
setUsers(newData);
};
const renderItem = ({ item }) => (
<TouchableOpacity style={{
flex: 1,
padding: 10
}}
onPress={() => { navigation.navigate('Client', { item: item }); }}
underlayColor='#ccc'
activeOpacity={0.1} >
<Item name={item.first_name} lastName={item.last_name} />
</TouchableOpacity>
);
console.log(search)
console.log(users)
return (
<SafeAreaProvider>
<SafeAreaView>
<Text style={{ color: '#666', margin: 15, fontSize: 20 }}>Clients actuels</Text>
<View style={{
width: '96%',
backgroundColor: 'white',
borderRadius: 5,
alignSelf: 'center',
marginTop: 20,
}}>
<View style={{ margin: 15 }}>
{isLoading ? <ActivityIndicator size="large" /> :
<FlatList
data={users}
renderItem={renderItem}
ItemSeparatorComponent={itemSeparator}
ListHeaderComponent={renderHeader}
keyExtractor={item => item.id.toString()}
value={search}
/>}
</View>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
export default Clients;