Pagination in React-Redux - reactjs

So I'm just trying to make a pagination component in react. Im currently using redux for my state management and using semantic-ui for the pagination component.
I have currently made a react component in my action.jsx file and have two other functions which one of them is for data fetching for my redux state and one other for the declaring the current active page value and set the new target url for data fetching.
export class Paginator extends React.Component {
state = {
page: [],
pages: []
}
handlePage(activePage) {
let pagenum = activePage;
let pagestring = pagenum.toString();
paginationUrl = '/api/v1/products/index/?page=' + pagestring; ----> Pass This Url
}
componentDidMount() {
axios.get("/api/v1/products/index", { withCredentials: true })
.then(response => {
this.setState({
page: response.data.page,
pages: response.data.pages
})
})
.catch(error => {
console.log("Check Login Error", error);
});
}
render() {
return(
<Pagination onPageChange={this.handlePage} size='mini' siblingRange="6"
defaultActivePage={this.state.page}
totalPages={this.state.pages}
/>
)
}
}
export function fetchProducts() {
return (dispatch) => {
dispatch(fetchProductsRequest())
axios
.get("To Here !")
.then(response => {
// response.data is the products
const products = response.data.products
dispatch(fetchProductsSuccess(products))
})
.catch(error => {
// error.message is the error message
dispatch(fetchProductsFailure(error.message))
})
}
}
The question is how am i able to pass the paginationUrl to the function below ? (Actually, there is no way i guess !).
Note: I am only able to use handlePage in the same component with the pagination component.
Waiting for suggestions, Thx in advance ;)

You could pass the URL to the fetchProducts function when dispatching actions on page changes.
handlePage(activePage) {
const url = `/api/v1/products/index/?page=${activePage}`
dispatch(fetchProducts(url))
}
And update the fetchProducts action creator to use the URL.
export function fetchProducts(url) {
return (dispatch) => {
dispatch(fetchProductsRequest())
axios
.get(url)
.then((response) => {
dispatch(fetchProductsSuccess(response.data.products))
})
.catch((error) => {
dispatch(fetchProductsFailure(error.message))
})
}
}
This is unrelated to the question but I would strongly recommend using React Query to simplify data fetching and synchronization.

Related

How to set state of other component inside an axios get method in react?

I'm using class-based components in react. I have few components named as follows: Blogs, BlogsClient, BlogCard. When Blogs mounts I make a call to a function inside BlogClient named as getBlogContent to fetch me data using axios.
setBlogs = (blogs) => {
this.setState({ "blogs": blogs });
}
componentDidMount() {
getBlogContent(this.setBlogs);
}
where getBlogContent is:
let getBlogContent = (setBlogs) => {
store.set('loaded', false);
axios.get(ADMIN_URL + '/getAllBlogs')
.then(response => {
store.set('loaded', true);
setBlogs(response.data.Response);
})
.catch(error => {
store.set('loaded', true);
store.set('errorMessage', error);
})
}
I'm able to fetch data and update my state properly. But If there comes any error inside Blogs or BlogCard(which is called inside Blogs) it goes inside the catch of getBlogContent whereas it should be only responsible for catching Axios error. What am I missing here?
Ok, so it's hard to tell without knowing these errors..
But nonetheless, you should avoid setting the component's state outside that component. So, your code'd become:
componentDidMount() {
const blogContent = getBlogContent();
if (blogContent !== 'error'j this.setBlogs(blogContent);
}
let getBlogContent = () => {
store.set('loaded', false);
return axios.get(ADMIN_URL + '/getAllBlogs')
.then(response => {
store.set('loaded', true);
return response.data.Response;
})
.catch(error => {
store.set('loaded', true);
store.set('errorMessage', error);
return 'error';
})
}

React and promise issues with fetch method

i'm new in react and i've got some issues with asynchronous fetch data :
i want to fetch github users
function fetchUser(username) {
return fetch(`https://api.github.com/users/${username}`)
.then(response => response.json())
.then(data => data)
}
export function getUserData(username) {
const object = {
profile: fetchUser(username),
}
console.log(object)
return object
}
and this is my method in my component
componentDidMount() {
getUserData(this.props.playerOne)
}
but this is what i got in my console
{profile: Promise}
i'm sure that i dont understand well this promise so could you help me to have not a Promise in my object but the data i'm fetching ? (if i log data in my fetch i got what i want)
You can make this function async and wait for the promise resolution.
export async function getUserData(username) {
const object = {
profile: await fetchUser(username),
}
console.log(object)
return object
}
then in your componentDidMount
componentDidMount() {
getUserData(this.props.playerOne)
.then((profile) => { this.setState({ profile }) })
}

Relay fetchQuery does not work after history.push BUT works fine in manual refresh

I'm developing a react-relay-graphql app with authenticaton and I want to show new messages count in Header component (navigation).
Here is Login Component code:
...
LoginMutation(username, password)
.then((resp) => {
if (resp.token) {
this._saveUserData(resp.expiredAt, resp.token)
fetchQuery(environment, query, {})
.then(data => {
const me = data.user.me;
this.setState({
Auth: {
user: {
fullName: me.fullName,
username: me.username,
isSeniorUser: me.isSeniorUser
}
}
})
this.props.setUser(this.state.Auth.user) // Redux
this.props.history.replace('/dashboard')
});
}
})
_saveUserData = (expiredAt, token) => {
localStorage.setItem(GC_USER_EXPIRES_AT, expiredAt)
localStorage.setItem(GC_AUTH_TOKEN, token)
}
...
And here is Header Component (It is inside Dashboard Component)
class Header extends Component {
componentDidMount() {
this.getMessagesCount()
}
getMessagesCount() {
fetchQuery(environment, NewMessagesQuery, {})
.then(data => {
const newMessagesCount = data.message != null ? data.message.countNewMessages.newMessages : '';
this.props.setNewMessagesCount(newMessagesCount) // Redux
});
}
render() {
return (
<>
{this.props.newMessages}
</>
)
}
}
The problem is after History.push it shows dashboard BUT fetchQuery does not even run and it returns data = {messages: null}, but when page manually refreshes, It works and new messages count is returned.
I figured it out.
In case anyone came to this problem, My cache Config in Environment.js was wrong. So it was trying to read data from cache for each request.

React Display Data from API Fetch & Map

i'm attempting to learn React by making a movie web app. Im trying to pull upcoming movies from a movie api, and display information from it, however i keep getting an error:
Line 37: Expected an assignment or function call and instead saw an
expression no-unused-expressions
Please excuse me as im not too familiar with this framework and im not a JS pro. Heres my code:
export default class Upcoming extends Component {
state = {
upcomingMovies: []
}
fetchUpcoming() {
fetch(`https://api.themoviedb.org/3/movie/upcoming?api_key=${API_KEY}&language=en-US&page=1`)
// We get the API response and receive data in JSON format...
.then(response => response.json())
// ...then we update upcomingMovies State
.then(data =>
this.setState({
upcomingMovies: data.results
})
)
}
componentDidMount(){
this.fetchUpcoming();
}
render() {
return(
<Container>
{ this.state.upcomingMovies.map((upcomingMovie) => {
console.log(upcomingMovie);
const title = upcomingMovie.title;
console.log(title);
<h1>{title}</h1>
})}
</Container>
)
}
}
Map function should return something to generate ui.
export default class Upcoming extends Component {
state = {
upcomingMovies: []
}
fetchUpcoming() {
fetch(`https://api.themoviedb.org/3/movie/upcoming?api_key=${API_KEY}&language=en-US&page=1`)
// We get the API response and receive data in JSON format...
.then(response => response.json())
// ...then we update upcomingMovies State
.then(data =>
this.setState({
upcomingMovies: data.results
})
)
}
componentDidMount(){
this.fetchUpcoming();
}
render() {
return(
<Container>
{ this.state.upcomingMovies.map((upcomingMovie) => (
<h1>{upcomingMovie.title}</h1>
))}
</Container>
)
}
}
You're missing a return statement in the last line of your map function. It should be return <h1>{title}</h1>
You should write fetchUpcoming by using arrow function. So, you can use this.setState() method on scope of fetchUpcoming function. EX:
const fetchUpcoming = async() {
try {
let response = await fetch(
`https://api.themoviedb.org/3/movie/upcoming?api_key=${API_KEY}&language=en-US&page=1`,
);
let responseJson = await response.json();
return this.setState({
upcomingMovies: responseJson.data.results
})
} catch (error) {
console.error(error);
}
}

React, The function does not load data

How to rewrite the function so that it is updated and loaded every time you change pages. The fact is that the loading function works only on one page, but it does not pass to others, how to change it?
function loadModel(model) {
return function(dispatch) {
dispatch(moveToPending(model))
const resource = require(`../resources/${model}`)
const resourceActions = bindActionCreators(resource.actions, dispatch)
const toaster = new Toaster(dispatch)
return new Promise((resolve, reject) => {
resourceActions[getFunctionName(model)]()
.then(res => {
resolve(model)
dispatch(resolveSubscriptions(model))
})
.catch(err => {
if (debug) console.error(err)
reject({ ...err, model })
dispatch(resolveSubscriptions(model))
toaster.error(`Could not load ${model}!`)
})
})
}
}
Update.
Here's the componentWillMount(), I already have it, what do I need to add to it?
componentWillMount() {
this.props.actions.subscribe(this.subscriptions)
.then(() => {
this.props.actions.fetchRegisters({year: this.state.currentYear, month: defaultMonths()})
.then(() => {
if (!this.props.registers.length) {
this.toaster.warning('There is no data for charts')
}
this.createReportState()
})
})
}
React has some lifecycle methods. You can use componentWillMount or componentDidMount for this purpose. You can pass this function as a prop to other pages and there you can call it in componentWillMount, something like:
componentWillMount() {
this.props.loadModel(//arg);
}
For reference: Component life-cycle methods

Resources