React Native | MobX vs route.params Performance - react-native

In a react native project using MobX, it would be more efficient to save the data for use on the next page. Or is it sending as params with the route? Suppose we are sending 50 pieces of data in Data.
//the page I will use the data
//option1
const {data} = route.params;
//option2
const {data} = Store;
Which one is better to use in terms of performance? Does the data I send with the route affect the rendering time of the opened page?

Related

How to perform a function in Vue3 only once when it is loaded

Inside the project, I used fake api, and in a component with setup, before the component is mounted, I get it and display it.
But the problem is that I make a series of changes on the same page on the captured apis, but when I render another page and go back to the previous page that has the api, this time because it is mounted, it executes the setup and the tasks I did on that page. They disappear. What can I do to make it run only when it is first loaded and not to run that code when it is mounted???
setup(){
const store = useStore();
async function getApi(){
await store.dispatch('task/getTasks')
}
getApi()
const tasks = computed(()=> store.state['task'].tasks)
return{tasks}
}

NextJS how to make pexels api pagination work

I am using NextJS to create a photo gallery with pexels api and want to add pagination to the project, but i didn't understand very well the documentation about pagination, so i dont know what i have to do to make this work.
What i want is to have a buttom at the bottom of the gallery saying "show more" and when i click it will show more photos.
this is my code:
First create two react states.
const [page, setPage] = useState(1);
const [perPage, setPerpage] = useState(10);
Here we are facing 10 images per page, if you want you can change how many images you want per page.
Then just convert your URL like the following.
const url = `https://api.pexels.com/v1/curated?page=${page}&per_page=${perPage}`
const data = await fetch(url)
Do that inside that useEffect hook. Now everything you want to load more just increment the perPage state. And if you want to get a new page and new image, then change the page state.

How to force a deep render in React Native on a specific interval?

How can I update a react component once every half second? I have a need to update a component to show new information as it flows in from an api. I want the component to rerender so it can display to new information at a specific interval.
In React, we could use forceUpdate. Unfortunately, in React Native, we don't have that luxury. Luckily, useState offers a deep render every time the setState function is called. This solution is a little hacky, but it gets the job done. Here's how it works:
const [inProgress, setInProgress] = useState(false); //This should be true when you want rerendering to happen.
const [updateCounter, setUpdateCounter] = useState(0); //This is the state the will force the update.
if (inProgress) {
setTimeout(() => setUpdateCounter(updateCounter + 1), 500);
}
This is the simplest way I've found to do it. The interval in this example is set to 500ms. However, it could be set to whatever you want. I chose half a second because I felt it offered a responsive enough feel to the user while also giving enough time for setState to run.

Render FlatList of Videos in a performant way

I am using a react native with expo. I have a lot of videos that I need to render (sort of like TikTok does). When I fetch about 30 videos and put them in the flat list in the renderItem method, it gets stuck and luggish. I was thinking about getting an amount of videos but sending to the renderItem method only 3 videos each time, and when the user will scroll down and reach index 2 it will shift the first index and append the fourth video from the fetched one. The idea was to have a small array of size 3 and change the items in it every scroll, in order to prevent rendering all the videos at once. That required array manipulation and caused a rerender each time the array of videos was updated(each change made sort of a flash - what was indicating a whole rerender).
My question is how should it be implemented in order the transition between the videos to be as fast and clean as possible from the client side perspective? What is the correct way to render videos in a flat list so it won't be stuck? I dont think It should be done that way, there has to be a better way.
This is what I have tried:
// challenges is an array coming from a fetch, just sliced it for the purpose of the example
// suppose it is an array that contains 30 items
const [currentVideos, setCurrentVideos] = useState([challenges.slice(0,3)]);
<FlatList
data={currentVideos}
renderItem={renderItem}
keyExtractor={(challenge, i) => challenge._id}
showsVerticalScrollIndicator={false}
snapToInterval={Dimensions.get("window").height - UIConsts.bottomNavbarHeight}
snapToAlignment={"start"}
decelerationRate={"fast"}
ref={(ref) => {
flatListRef.current = ref;
}}
onScrollToIndexFailed={() => alert("no such index")}
onViewableItemsChanged={onViewRef.current}
onScrollEndDrag={() => (scrollEnded.current = true)}
onScrollBeginDrag={beginDarg}
></FlatList>
useEffect(() => {
// just wanted to check on 3 videos
if (currentlyPlaying === 2) {
let temp = currentVideos;
temp.shift(); // pop the top item
temp.push(challenges[4]) // append a new one
setCurrentVideos(temp);
}
}, [currentlyPlaying]);
const onViewRef = useRef(({ viewableItems }) => {
// change playing video only after user stop dragging
scrollEnded.current && setCurrentlyPlaying(viewableItems[0]?.index);
});
I would avoid manipulating the data array and doing business logic inside of the component.
Besides, you can achieve your desired behaviour without the need to manipulate your data array at all, with the maxToRenderPerBatch FlatList prop. As mentioned in the official RN docs for FlatList optimization techniques.
You should avoid using anonymous functions and objects inside of your component's properties, move them outside of the return statement and use the useMemo and useCallback hooks to avoid their unnecessary recreation on every re-render. For example instead of writing your code like this:
const App = () => {
return (
<FlatList
keyExtractor={(challenge, i) => challenge._id}
snapToInterval={Dimensions.get('window').height - UIConsts.bottomNavbarHeight}
/>
);
};
A better approach would be to re-write it to something like this:
const App = () => {
// Because of useCallback, the keyExtractor function will be memoized and won't recreate itself on every re-render
const keyExtractor = useCallback((challenge, i) => challenge._id, []);
// useMemo is almost the same as useCallback, but it is used to return non-function types
// Defining your snapToInterval variable like this will cause it to memoize its value and it
// won't recreate itself on every re-render
const snapToInterval = useMemo(() => Dimensions.get('window').height - UIConsts.bottomNavbarHeight, []);
return (
<FlatList
keyExtractor={keyExtractor}
snapToInterval={snapToInterval}
/>
);
};
If you haven't already, you should consider extracting the component returned from the renderItem function to a different file and applying React.memo to it.
Note: try not to overuse useCallback and useMemo. You can find good and detailed explanation of why not to overuse them here and here.
If you're able to, you should optimize your videos before uploading them to the server. You can optimize your client side part of the app as much as you want, but if the content isn't properly optimized, you won't be able to achieve a smooth and performant experience regardless of your efforts.
Here's also some articles describing how you can optimize your FlatList component:
How did I optimize my React Native FlatList?
8 ways to optimize React native FlatList performance
Optimizing a React Native FlatList With Many Child Components
React Native Performance Optimisation With Hooks
React Native: Optimized FlatList of videos
I hope that some of this will be helpful to you. Good luck.
I have been searching for a solution as well. I have worked out a solution based on some previous work using InViewPort. you can check it out here https://github.com/471Q/React-Native-FlatList-Video-Feed

React Native: Didn't rerender the component after data was updated

i have two screens one where the profile information is showing and another screen to edit the information. If i entered the first screen profile it's shows me the right data from the database. Then i move to the next screen where i can change the Information everthing worked so far. But if I go back to the previous screen i still see the old data. So there is no rerendering.
But if i navigate to the other screen that screen fetched the new data. and the call getCurrentUserProfile is executed
This ist the screen with the profile information about the user.
const ProfileScreen = props => {
const [userObj, setUserObj] = useState({});
useEffect(() => {
let mounted = true;
getCurrentUserProfile().then(user => {
if (mounted) {
setUserObj(user);
}
console.log(user)
});
return () => mounted = false;
}, []);
console.log("----b------") // This is only output on the first call
}
How can i fix this. Is there a way when in the database is something changed, so the component rerender and fetches the new data.
Thanks.
You are probably using #react-navigation package. So, if you want to refetch data when come back to the previous page, you can use https://reactnavigation.org/docs/use-is-focused on that “previous” page.
Just look at their docs, you will get the idea.
P.S: Usually we don't unmount components directly. In React Native, we use navigator to mount/unmount components