Flatlist is very slow in using big data in react native - react-native

i have a big data list of products thats paginate, in every page it load 10 item, but when i add new items to itemlist,flatlist gets very slow,As the number of pages increases, so does the loading time of new products,The function of the choose button is also slowed down.
How to speed up loading I tried all the best methods but it still did not work. Did not React Native really solve this problem?
export default function Products(props) {
const toast = useToast();
const [isLoading, setSetIsLoading] = useState(true);
const [items, setItems] = useState([]);
const [fetchStatus, setFetchStatus] = useState(false);
const [page, setPage] = useState(1);
const [sending, setSending] = useState(false);
async function getProducts() {
let token = await AsyncStorage.getItem('#token');
let data = {
token: token,
page: page,
};
await get_products(data)
.then(res => {
setItems([...items, ...res.data.data.docs]);
setPage(res.data.data.nextPage);
})
.catch(err => {
console.log(err);
});
}
async function getNextPage() {
let token = await AsyncStorage.getItem('#token');
let data = {
token: token,
page: page,
};
await get_products(data)
.then(res => {
setItems([...items, ...res.data.data.docs]);
setPage(res.data.data.nextPage);
})
.catch(err => {
console.log(err);
});
}
async function selectProduct(id) {
setSending(true);
console.log({id});
let token = await AsyncStorage.getItem('#token');
let data = {
product_id: id
};
await select_products(data,token).then(res => {
toast.show({
description:res.data.message
})
setSending(false);
}).catch(rej => {
console.log({rej})
toast.show({
description:rej?.response?.data.message,
})
setSending(false);
})
}
useFocusEffect(
React.useCallback(() => {
getProducts();
return () => {
setItems([]);
setPage();
};
}, []),
);
renderItem =({item}) => (
<Card
selectProduct={id => selectProduct(id)}
sending={sending}
obj={item}
/>
)
return (
<View mb={20}>
<FlatList
data={items}
extraData={items}
removeClippedSubviews={true}
renderItem={renderItem}
keyExtractor={(item) => `${item._id}-item`}
onEndReached={getNextPage}
maxToRenderPerBatch="13"
ListFooterComponent={() => {
return <ActivityIndicator color="orange" size="large" />;
}}></FlatList>
</View>
);
}

Did you use **map method **?
It can help you for more easily loading data

Related

React Native - context + firebase

I need to pass one value from firestore to application context. I don't know where am I going wrong? Has anyone had a similar problem? I searched the website but couldn't find anything similar.
export const AuthProvider = ({children}) => {
const [user, setUser] = useState();
const [contextWeight, setContextWeight] = useState();
}
return (
<AuthContext.Provider
value={{
user,
setUser,
contextWeight,
setContextWeight,
unit: async () => {
await firestore()
.collection('users')
.doc(auth().currentUser.uid)
.collection('products')
.doc('product')
.get()
.then(( documentSnapshot ) => {
if( documentSnapshot.exists ) {
setContextWeight(documentSnapshot.data().weightUnit);
}
}).catch(error => {
console.log(error);
})
}}>
{children}
</AuthContext.Provider>
);

Promise Rejection with axios. try to make HTTP instead of HTTPs [ duplicate ]

I pull data from the API and write it to the application with usestate() when the app runs there are no problems, but after 10-30 seconds I get this error.
Here is my code.
const App = () => {
const [datas, setDatas] = useState([])
const res = async () => {
const response = await axios.get("http://hasanadiguzel.com.tr/api/kurgetir")
setDatas(response.data.TCMB_AnlikKurBilgileri)
}
res()
return (
<SafeAreaView style={style.container}>
<View>
{datas.map((item) => {
return (
<KurCard
title={item.Isim}
alis={item.BanknoteBuying}
satis={item.BanknoteSelling}
/>
)
})}
</View>
</SafeAreaView>
)
}
How can I fix this ?
Hi #n00b,
The problem is with your URL Protocol.
const App = () => {
const [datas, setDatas] = useState([]);
const res = async () => {
try {
const url = "https://hasanadiguzel.com.tr/api/kurgetir";
const response = await axios.get(url);
const data = await response.data;
console.log(data.TCMB_AnlikKurBilgileri); // check you console.
setDatas(response.data.TCMB_AnlikKurBilgileri);
} catch (error) {
console.log(error);
}
};
useEffect(() => {
res();
}, []);
And also check this out:- Codesandbox.
And please read this Stack Overflow discussion for better understanding:- stackoverflow

making several api calls slows down react native app

So I am calling getUserProducts() (to show the updated list) whenever a product is added to the list and whenever a product is deleted from the list. But I've noticed when I add several items to the list through the dropdown, some times the product doesn't show in the list/getUserProducts isn't called (and then if I add another product it'll then show the previous added product) I'm assuming its because I'm calling it every time I add and that's making it slow? Is there a way I can work around this to optimize it?
const App = () => {
const [products, setProducts] = useState<ProductType[] | []>([]);
const [userProducts, setUserProducts] = useState<ProductType[] | []>([]);
const [toggleCheckBox, setToggleCheckBox] = useState(false);
const [value, setValue] = useState(' ');
const [isFocus, setIsFocus] = useState(false);
const [visible, setVisible] = useState(false);
const [productId, setProductId] = useState('');
const [product, setProduct] = useState('');
const [num, setNum] = useState('');
const [amount, setAmount] = useState('');
const submitForm = async () => {
let body;
body = {
product_id: productId,
product: product,
num: num,
amount: amount,
};
const response = await postProduct(body);
if (response == undefined) {
return;
}
};
const getProducts = async () => {
try {
const response = await axios.get('http://192.168.1.32:3000/api/products');
setProducts(response.data);
} catch (error) {
// handle error
alert('no');
}
};
const getUserProducts = async () => {
try {
const response = await axios.get(
'http://192.168.1.32:3000/api/user_products',
);
setUserProducts(response.data);
} catch (error) {
// handle error
alert('no');
}
};
React.useEffect(() => {
getProducts();
getUserProducts();
console.log(userProducts);
}, []);
return (
<>
<Provider>
<Dialog visible={visible} onDismiss={() => setVisible(false)}>
<DialogHeader title="Add to your list" />
<DialogContent>
<Dropdown
style={[styles.dropdown, isFocus && {borderColor: 'blue'}]}
data={products}
search
maxHeight={300}
labelField="product"
valueField="num"
placeholder={!isFocus ? 'Select item' : '...'}
searchPlaceholder="Search..."
value={value}
onFocus={() => setIsFocus(true)}
onBlur={() => setIsFocus(false)}
onChange={item => {
setValue(item.num);
setProductId(item.product_id);
setProduct(item.product);
setNum(item.num);
setIsFocus(false);
}}
/>
<TextInput
label="quantity"
variant="standard"
onChangeText={text => {
setAmount(text);
console.log(text);
}}
/>
</DialogContent>
<DialogActions>
<Button
title="Cancel"
compact
variant="text"
onPress={() => setVisible(false)}
/>
<Button
title="Add"
compact
variant="text"
onPress={() => {
setVisible(false);
submitForm();
console.log('added');
getUserProducts();
}}
/>
</DialogActions>
</Dialog>
{userProducts.length > 0 ? (
userProducts.map(userProduct => (
<ListItem
title={
userProduct.product +
' x' +
userProduct.amount +
' num: ' +
userProduct.num
}
onPress={async () => {
await deleteProduct(userProduct.product_id);
console.log('deleted');
getUserProducts();
ToastAndroid.show('Done', ToastAndroid.SHORT);
}}
trailing={
<CheckBox
disabled={false}
value={toggleCheckBox}
onValueChange={newValue => setToggleCheckBox(newValue)}
/>
}
/>
))
) : (
<Text>Nothing in your list yet</Text>
)}
</Provider>
</>
);
};
export default App;
I'm pretty certain that you aren't experiencing "lag" but race conditions.
See, when you create an item, you call submitForm() and getuserProducts() and both are async functions. Depending on how long the individual requests take, or how their execution gets scheduled getuserProducts() may very well finish before submitForm(). The new data then only reaches the server after you fetched the (not so) new data.
Consider the following code (it's just a simplified version of your app):
import React, { useState } from 'react';
interface ProductType {
id: number;
name: string;
}
export default function NotWorking() {
const [products, setProducts] = useState<ProductType[]>([]);
const createProduct = async () => {
await serverCreateProduct(`product: ${products.length}`);
console.log('product created');
};
const getProducts = async () => {
setProducts(await serverGetProducts());
console.log('products loaded...');
};
return (
<div>
<button
onClick={() => {
createProduct();
getProducts();
}}
>
Add
</button>
<h2>List:</h2>
<ul>
{products.map((product) => (
<li key={String(product.id)}>{product.name}</li>
))}
</ul>
</div>
);
}
const _userProducts: ProductType[] = [];
async function serverGetProducts() {
return new Promise<ProductType[]>((resolve) => {
setTimeout(() => {
resolve([..._userProducts]);
}, 300);
});
}
async function serverCreateProduct(name: string) {
return new Promise<void>((resolve) => {
setTimeout(() => {
_userProducts.push({ id: Math.random(), name });
resolve();
}, 500);
});
}
If you execute it, you will see that getProducts() finishes before createProduct(), so that result cannot include the new data.
You should await both of them, in order to get what you want, for example:
const createProduct = async () => {
await serverCreateProduct(`product: ${products.length}`);
console.log('product created');
setProducts(await serverGetProducts());
console.log('products loaded');
};
// ...
<button onClick={() => createProduct()}>Add</button>
See the code working here.

How to convert react native signature canvas functional component to class component

I am new to react native. I do not know how to convert Functional component to class component. please help. here is my code of react native signature canvas code which is in functional component I want to convert it to class component please help thanks.
const ref = useRef();
const handleSignature = signature => {
const path = FileSystem.cacheDirectory + 'sign.png';
FileSystem.writeAsStringAsync(path, signature.replace('data:image/png;base64,', ''), {encoding: FileSystem.EncodingType.Base64}).then(res => {
// console.log(res);
// FileSystem.getInfoAsync(path, {size: true, md5: true}).then(file => {
FileSystem.getInfoAsync(path).then(file => {
console.log(file);
setSingleFileSIGN({ singleFileSIGN: file.uri});
console.log(singleFileSIGN)
})
}).catch(err => {
console.log("err", err);
})
};
const handleEmpty = () => {
console.log('Empty');
};
const handleClear = () => {
console.log('clear success!');
};
const handleEnd = () => {
ref.current.readSignature();
};
<View style={{flex: 1, width:355,
...Platform.select({
android: {
marginBottom:-80,
borderColor: '#FF8C00',
borderWidth:1
// marginBottom:-150
},
}),
}}>
<SignatureScreen style={{height: '400%'}}
ref={ref}
onEnd={handleEnd}
onOK={handleSignature}
onEmpty={handleEmpty}
onClear={handleClear}
descriptionText={'Sign here!'}
/>
</View>
const signatureRef = createRef()
clearSignature = async () => {
await signatureRef.current?.clearSignature()
}
handleOK = async (signature) => {
const sign = signature.split(",").pop()
await this.setState({
signatureVal: sign
})
// onOK(signature); // Callback from Component props
};
handleEnd = async () => {
await this.setState({isScrollEnabled: true})
await signatureRef.current?.readSignature()
}
render(){
<View>
<SignatureScreen
ref={signatureRef}
onOK={this.handleOK}
onEnd={this.handleEnd}
androidHardwareAccelerationDisabled={true}
onBegin={async () => {await this.setState({
isScrollEnabled: false
})}}
/>
</View>
}

react native - why is my console.log returning [] but items get rendered on screen?

I am trying to access the object obtained from my API get request but I keep getting Array[] returned in the console.log while the items get rendered on the screen.
Can someone spot where I went wrong?
const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const loadPosts = async () => {
setLoading(true);
const response = await messagesApi.getMessages();
setLoading(false);
if (refreshing) setRefreshing(false);
if (!response.ok) return setError(true);
setError(false);
setPosts(response.data);
};
useEffect(() => {
const newsocket = io.connect("http://ip:port");
loadPosts();
console.log(posts); // not working
newsocket.on("connect", (msg) => {
setSocket(newsocket);
});
return () => newsocket.close();
}, []);
return (
<FlatList
data={posts}
keyExtractor={(post) => post.id.toString()}
renderItem={({ item, index }) => (
<MessagesList
title={item.title}
onPress={() =>
navigation.navigate(routes.CHAT, { message: item, index, updateView })
}
/>
)}
/>
);
ISSUE
console.log executes before getting an API response.
SOLUTION
console.log would work when you add posts in dependency like
useEffect(() => {
console.log(posts);
}, [posts]); // added posts here