react query infiniteQuery does not fetch next page - react-native

Like the title explains, I can't seem to get the next set of results/page on request using react-query infiniteQuery. I also made a snack from their example code but still nothing.
It looks like the pageParam never gets incremented when fetchNextPage is called. I've tried version 3 and 4 with same results.
So I'm not sure if I should be incrementing the nextCursor manually. I can see nothing in the docs that suggests that I have to do so.
snack example
const fetchProjects = async ({ pageParam = 0 }) => {
const res = await fetch(`https://api.instantwebtools.net/v1/passenger?
page=${pageParam}&size=10`)
return res.json()
}
const List = () => {
const {
data,
error,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
status,
} = useInfiniteQuery({
queryKey: ['test'],
queryFn: fetchProjects,
getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
});
const loadMore = () => {
fetchNextPage()
}

Turns out the API I was using as test does not return any way for me to tell if there is more data to fetch. ie. no nextCursor property.

Related

fetch returns first empty array, after that it returns response

I'm making my final degree project and now I'm involved in the part to show towns on a map using data from a backend URL.
The problem is that fetch returns at first an empty array, and I need it to stay loading until the variable is a valid JSON.
const [isLoading, setLoading] = useState(true);
const [markers, setMarkers] = useState([]);
const getTowns = async () => {
try {
const response = await fetch(`${baseUrl}/towns`);
const json = await response.json();
setMarkers(json.data);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
};
useEffect(() => {
getTowns();
}, []);
Another question is: Why when I put a console.log('whatever') it appears more than one time on the console. Don't understand why
What I need is fetch to setLoading(false) only when response is a JSON, not an empty array
What you can do is add these 2 hooks to your code:
A state for the returned response (with initial value an empty array)
A useEffect which will set to false isLoading once the response state change value
const [response, setResponse] = useState([]);
const getTowns = async () => {
try {
setResponse(() => await fetch(`${baseUrl}/towns`));
const json = await response.json();
setMarkers(json.data);
} catch (error) {
console.error(error);
}
};
useEffect(() => {
setLoading(() => false);
}, [response]);
your code is fine you juste don't need the isLoading useState Hook. you can test with the value of markers
Why when I put a console.log('whatever') it appears more than one time on the console. Don't understand why
when the component first render getTowns runs in useEffect and since it updates the state the component renders again. learn more here about react component lifecycle
what I suggest is when you are returning your jsx you check if markers is still empty
const [markers, setMarkers] = useState('');
if(markers === ''){
return (<div>Loading...<div/>)
} else {
return(<>
.... what you need to return in you component
</>)
}

How to get state in Nuxt js with composition api?

setup(){
const columns = computed(()=>store.state['subCategory'].subCategoryColumnsData[subCategoryName.value]);
const { fetch } = useFetch(async () => {
await store.dispatch('subCategory/getColumnsQuery', {
categories: subCategoryId.value,
page: 1,
subCategoryName: subCategoryName.value,
})
});
fetch();
}
I want to switch between pages in my project. Whenever I switched another page, I send request to get data with latest updates. This code works well for the first time when page was loaded, but it doesn't work when I switched from one page to another page. But if I check store state, I can see it in store. If I visit same page second time , I can see data this time.
But if I change my code like this, it works well. I did not get why it does not work true in the first sample
setup(){
const columns = ref([])
const { fetch } = useFetch(async () => {
await store.dispatch('subCategory/getColumnsQuery', {
categories: subCategoryId.value,
page: 1,
subCategoryName: subCategoryName.value,
})
}).then(() => (columns.value = store.state['subCategory'].subCategoryColumnsData[subCategoryName.value]));
fetch();
}
Can you test it? sample:
const state = reactive({ columns: computed(() => yourstore })
// do not need to call fetch because this hook is a function
useFetch(async () => { await store.dispatch(url) })
return {
...toRefs(state),
}

React Native Hooks initializer not taking the correct value

What I am trying to do is sync a list of attendees from an online database, and if the current user is in the list, then disable a button, else enable the button.
I am using react native hook (I am not sure if I am using the term correctly as I am fairly new to react), in order to set the value of disabling the button.
The issue that I am facing is that the value is getting initialized to false, even tho it should clearly get initialized to true.
After adding some logging I made sure that the function is executing correctly and reaching the code where it sets the value to true.
const [buttonDisabled, changeButtonState] = useState( () => {
var database = firebase.database();
var userId = firebase.auth().currentUser.uid;
const dbRef = firebase.database().ref();
var Attendees = [];
var disable = false;
dbRef.child("gameAttendees").child(gameinfo.gameID).get().then((snapshot) => {
if (snapshot.exists()) {
Attendees = snapshot.val().Attendees;
for(var i=0;i<Attendees.length;i++){
if(Attendees[i]==userId){
return true;
}
}
} else {
console.log("no value");
return false;
}
}).catch((error) => {
console.error(error);
});
});
Adding an example of an async mount effect:
const Comp = () => {
const [s, setS] = useState(); // State will be undefined for first n renders
useEffect(() => {
// Call the async function and set the component state some time in the future
someAsyncFunction().then(result => setS(result));
}, []); // An effect with no dependencies will run only once on mount
return </>;
};

setState inside an async search

I am trying to set a stateful object with results I get from an async search and I'm getting some errors and strange behavior.
I'm using algoliasearch to run this search. Here's the code in pseudo, I can share the full code if needed, but I don't think it's important. The search works just fine and I get results (see comments below)
const [results, setResults] = useState(null);
index.search(searchQuery, {...requestOptions})
.then(({ hits }) => {
fetchedResultsArray = hits?.map((result) => {
...
return {...}
}
// console.log("fetchedResultsArray", fetchedResultsArray)
setResults(fetchedResultsArray)
).catch
It causing the app to act funny, get stuck, sometimes crash. Sometimes I get this (very long) error: Warning: Please report: Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code: {"1531":{"module":"NativeAnimatedModule","method":"startAnimatingNode"}...
When I comment setResults(fetchedResultsArray) and uncomment the console log before it, it prints the results and the app acts normal. Reverting back to setResults(fetchedResultsArray) and things go wrong again. I am doing something wrong/illegal, but what?
Another important thing to mention is that I'm using Expo SDK 41 beta 2.
UPDATE
Patrick, you pointed out what I am doing wrong. Let me show you in a little more depth what I do in my SearchScreen, again abbreviated:
const SearchScreen = () => {
// I get the initSearch function from a custom hook and you already see above what the function is.
const [
initSearch,
...
] = useSearch();
// Then I fire the search when the screen loaded
useLayoutEffect(() => {
if (region) {
initSearch({ searchQuery, region, filterOptions, priceOptions });
}
}, [filterOptions, initSearch, priceOptions, region, searchQuery]);
...
my custom hook is something like this:
export function useSearch() {
const [readyToAnimateAfterSearch, setReadyToAnimateAfterSearch] = useState<boolean>(false);
const [results, setResults] = useState<Result[] | null>(null);
const setAlert = useStore(useCallback((state) => state.setAlert, []));
const setProgressBarVisible = useStore(useCallback((state) => state.setProgressBarVisible, []));
const [radius, setRadius] = useState<number>(0);
const initSearch = useCallback(
async ({ searchQuery, region, filterOptions, priceOptions, loadMore = false }) => {
...
},
[results, setResults, setAlert, setProgressBarVisible]
);
return [
initSearch,
results,
setResults,
radius,
readyToAnimateAfterSearch,
setReadyToAnimateAfterSearch,
] as const;
Could you please suggest an alternative way to run this as an answer. No need to go into details, just so I get the flow of how you would handle this. Thank you!
My main issue was me using results inside the initSearch function, instead of using a stateUpdater function and removing results from the deps array.

React Native - useEffect / setState - fetching data from api

I'm learning RN and writing a simple app about lottery results.
I am facing this problem:
I need to print the results that i am fetching from an api when the component mounts, using useEffect and setState. Everything works regarding the api call and the item construction, i can console.log the resulting array [loadedResults] which i want to be 'results' in the state.
But, the state its not being modified so the state object remains always empty.
I am clearly missing something in the setState step.
I have tried to make it a function and also using variable.then(...).
I am using a for loop because there are hundreds of results in the api and i only want 10 of them.
this is my code:
const ResultadosScreen = props => {
const [results, setResults] = useState({});
useEffect(() => {
async function fetchData() {
const response = await fetch('apiUrlGoesHere');
// response.json().then((response => setResults(response)));
const resData = await response.json();
const pastResults = resData.past;
const loadedResults = [];
for (let r = 0; r < 11; r++){
loadedResults.push(
new FakeResult(
r,
pastResults[r].drawingDate.substring(0,10),
pastResults[r].nr,
pastResults[r].numbers
)
);
}
console.log(loadedResults); // I GET THE EXPECTED 10 ITEMS IN THIS CONSOLE LOG
(loadedResults => setResults(loadedResults)) //HERE IS WHERE IM MISSING SOMETHING
}
fetchData()
});
console.log(results);
//I GET UNDEFINED FROM THIS CONSOLE LOG
return (
<View style={styles.screen}><Text style={styles.headerTitle}>{}</Text></View>
);
};
export default ResultadosScreen;
Thanks for your help