Getting data with React and Spring pagination - reactjs

I'm using Spring data Pagination with React to get some data. I have two ways of getting the data from the backend, the first one when the component re-render. The second way when clicking on a button.
const searchButton = () => {
isLoading(true);
searchOrder(searchInput, pageNumber, 'name').then((res) => {
setOrders(res.data.content);
setTotalElements(res.data.totalElements);
setCurrentPage(res.data.number);
setItemsCountPerPage(res.data.size);
isLoading(false);
});
};
useEffect(() => {
isLoading(true);
getOrders(pageNumber, 'name').then((res) => {
setOrders(res.data.content);
setTotalElements(res.data.totalElements);
setCurrentPage(res.data.number);
setItemsCountPerPage(res.data.size);
isLoading(false);
});
}, [pageNumber, refreshPage]);
When clicking on the button I will get the data, but when trying to go to the next page, it will fire the useEffect and will get the data from it. My question: how should I go to the next page from the data that I got when clicking the button?

I solved this by adding the content of the search button in the useEffect method as a conditional statement.

Related

react native navigation useFocusEffect triggered before goBack

I use react-native-navigation and redux. I have a Stack Navigator with two screens.
The second screen uses some data stored in redux by the first screen.
The first screen has a function that resets that data inside a useFocusEffect hook so when the focus is back on the first screen all the data will be erased.
// First Screen
useFocusEffect(
useCallback(() => {
dispatch(clearAllData());
}, []);
);
The problem is that if I try to go back to the first screen using navigation.goBack() somehow the data is cleared before the second screen is completely unmounted and it throw an error.
// Second Screen
const some_params = useSelector(state => state.data.some_params);
// error: can't read property "some_params" of null
I tried adding a little timeout on the dispatch(clearAllData()) and it worked but I don't think it's a valid solution.
I can use the optional chaining like state?.data?.some_params but I will have to use it everywhere.
Is it possible to trigger clearAllData being sure the second screen is completely unmounted?
Edit
I've tried both useIsFocused and navigation.pop() but none of them works as expected.
Finally I found a solution using InteractionManager.runAfterInteractions
useFocusEffect(
useCallback(() => {
const task = InteractionManager.runAfterInteractions(() => {
dispatch(clearAllData());
});
return () => task.cancel();
}, [])
);
Can you try clearing data like this
import { useIsFocused } from '#react-navigation/native';
const focused = useIsFocused()
useEffect(()=>{
if(focused){
dispatch(clearAllData());
}
},[focused])

Fresh Call To API EndPoint on Button Click in React JS

I haven API endpoint, that gives me a random text, on each call. As of now, when the React Component loads for the first time, a call goes through to the API and I get the random text.
The code looks like this. I am using redux for state management.
const RandomQuoteList = ({ todo, isLoading, startLoadingTodos }) => {
useEffect(() => {
startLoadingTodos();
}, []);
const [inputValue, setInputValue] = useState(`HelloThere`);
function changeRandomText(e) {
// const item = e.target.value;
var something = Math.random();
console.log(`changeRandomText clicked + ${something}`);
setInputValue(`changeRandomText clicked + ${something}`);
console.log(inputValue);
}
const loadingMessage = <div>Loading todos...</div>;
const content = (
<GeneralWrapper>
<RandomQuoteItem todo = {todo} inputValue = {inputValue}/>
<Button onClick={changeRandomText}>Get A New Quote</Button>
</GeneralWrapper>
);
return isLoading ? loadingMessage : content;
};
const mapStateToProps = state => ({
isLoading: getTodosLoading(state),
todo: getTodos(state),
});
const mapDispatchToProps = dispatch => ({
startLoadingTodos: () => dispatch(loadTodos()),
});
export default connect(mapStateToProps, mapDispatchToProps)(RandomQuoteList);
Now, I want to be able to use a simple button click to 'refresh' the API call. That way, the API endpoint will be triggered and a fresh new text will get updated.
I have looked at the following stack over flow questions.
React: re render componet after button click
How to refresh React page/component on Button click after POST
ReactJs : How to reload a component onClick
But, I am not getting far. I am able to randomly change the state of a text component, and that is changing the text component. So, I have the random value change part taken care of.
The target component looks something like this. When I click the button on the above component, the below component updates the random text no problem.
const RandomQuoteItem = ({ todo,inputValue }) => {
//set the style for the display.
// const Container = todo.isCompleted ? TodoItemContainer : TodoItemContainerWithWarning;
const Container = TodoItemContainer;
return (
<Container>
{/* this is where you show your API response single items. */}
<h3>{todo.quoteContent}</h3>
<h4>{todo.quoteAuthor}</h4>
<h4>{todo.quoteIdentifierString}</h4>
<p>-------------------------------</p>
<h4>{todo.quoteIdentifierCompadre}</h4>
<h4>{todo.dateTimeOfResponse}</h4>
<h4>{todo.detailsAboutOperation}</h4>
<p>{inputValue}</p>
</Container>
);
}
Now, how do I link this random state change to my RandomQuoteItem state, so, it makes fresh data call?
Based on the comment from rahuuz above, I ended up with this. and it worked.
function changeRandomText(e) {
// const item = e.target.value;
var something = Math.random();
console.log(`changeRandomText clicked + ${something}`);
setInputValue(`changeRandomText clicked + ${something}`);
console.log(inputValue);
startLoadingTodos(); //this specific line solved the problem.
}
I think, it worked in my favour that I already had redux and reducers and all of that hooked up. If that was no the case, this specific solution may not have worked, I think.
Button click calls the startLoadingTodos function, which in turn calls the API and that returns data, updating the redux state, and component also updates.

How do I create a loader that will load in between images when they load in an image slider in react js

I am a beginner in learning react, I create a project portfolio using image slider, I want to be able to create a loader in between whenever the image load one after the other.
Here is the link to the code
https://github.com/motuncoded/fatah-website/blob/main/src/components/ImageGuitarSlider.js
Unfortunately there is not much info to go on, but you can use a useEffect to achieve this. Here is a generic example you can start off with: In your ImageSilder add a useState for loading and in the useEffect use a promise with a timeout of 1.5 seconds.
const [loading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
const loadingHandler = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, 1500)
}
}
loadingHandler.then(() => setLoading(false))
}, [ticket])
Whenever the ticket state is changed it will trigger useEffect (we pass the ticket as a dependency to useEffect) which will set the loading state to true, wait 1.5 seconds and set loading to false. You can use this loading state to display a loading icon, for example, a spinner or loading bar.
This may not be a full solution, based on the info provided in your description, it can be a starting point in what you are looking for.

React multiple http calls when navigating the application using the URL

I have a component which has filtering, searching and pagination capabilities. What I'm trying is to create a queryString and attach to the URL such that I can later copy and paste it in another browser so that I can reuse the filters.
To extract the query params from the URL I'm using the useLocation hook
const useQuery = () => new URLSearchParams(useLocation().search);
const pageNo = useQuery().get('page') ?? 1;
I'm using the useEffect hook to track for changes of the page query parameter value, and dispatch an action which will update the pageNo in the state object of my reducer.
React.useEffect(() => {
dispatch({
type: actionDescriptor.CHANGE_PAGE,
payload: pageNo
});
}, [pageNo]);
I have another useEffect hook which handles the fetch of the data, and gets triggered when the pageNo changes. I'm using the useNavigate to create and navigate to the new location if the http call was successful
const nav = useNavigate();
React.useEffect(() => {
(async function get() {
const response = // make http call and get response
if (response.status === 200) {
dispatch({
type: actionDescriptor.FETCH_SUCCESS,
payload: {
data: response.data['value'],
}
});
nav (`/data?page=${state.pageNo}`);
}
/// handle error
}
})();
}, [state.pageNo, state.pageSize, state.filter]);
When I'm navigating using the UI, selecting a different page for example, all works well, there is a single http call, the browser url is updated as expected (e.g. localhost/mydata?page=2). If however I'm copying the url and paste it in another window, it makes two http calls, and renders the dom twice. What might be the cause for this?
my guess is due to the parameters you are listening on state.pageNo, state.pageSize, state.filter. I'm assuming all of these are null/empty at the beginning of your app. Once you copied and pasted the url, two of these parameters will change which will cause the useEffect to be called twice.
put in a console.log in the useEffect to confirm that. Once that's confirmed, I would re-examine the list of parameters to see if you need to listen to all of them.
I would take a look at the pageNo. It looks like it might be changing from default value to 2 since you have 2 useEffects probably firing for the same render.

How to dynamically Load API Data on a button Click in React Native

I am a starter in React Native. I have an API that dynamically displays the number of levels on a page. Every time the user clicks on the button, I want to fetch an API and navigate to another page. I have defined three on click events for this, but I want to clean up my code and write with the help of one OnClick event.
My levels are as follows
//Level1
async Level1() {
const datavalue = await getResultValue('url1');
this.props.navigation.navigate('Final','getSomething');
}
//Level2
async Level12() {
const datavalue = await getResultValue('url2');
this.props.navigation.navigate('Final','getSomething');
}
//Level3
async Level3() {
const datavalue = await getResultValue('url3');
this.props.navigation.navigate('Final','getSomething');
}
Each an every level, there is a corresponding API. Is there a way I can achieve it with the help of One OnClick Event?
Any help would be appreciated. Thank you in advance.
async navigateToFinalScreen(params){
data = await fetch(params.url);
this.props.navigation.navigate(params.screenToNavigate, 'getSomething');
}
/* calling This method */
this.navigateToNextScreen(
{ url:"url",
screenToNavigate:"Final" }
)

Resources