Implementing server-side pagination with Ngrx and using router parameters to navigate pages

In my store, I have a simplified state tree structure:

{
    routerReducer: {
        state: {
            url: '/blog'
        },
        queryParams: {
            category: 'home'
        }
        params: { }
    },
    blog: {
        posts: {
            entities: { ... }
            loading: false,
            loaded: false,
            pagination: {
                sort: 'date',
                filters: {
                    category: 'home',
                    tag: 'testTag'
                },
                page: 1
            }
        }
    }
}

Essentially, I want to pass the router state down to the blog state for pagination purposes, but only if the current URL belongs to that module. The pagination for the blog -> posts state will be dependent on the URL parameters already defined in the state. It might not be the most conventional approach as it may lead to multiple sources of truth, but I intend to use this pagination state to define the entities in my store. This means that if I move pages or change filters, I will clear all entities and refresh with paginated content from the API.

Here is the flow I have in mind:

  • Router navigation event e.g. /blog/2 (page 2 via queryParam)

  • Router action is dispatched and handled by the router reducer to update that part of the state tree

  • Side effect triggered on router navigation event, checking if the URL matches the blog module e.g. "/blog/*" (which might contain URL parameters like ?category=home), then composing our local pagination state in the blog state tree, and finally dispatching a loadPosts action based on that state

What do you think of this flow? Is this the correct approach to achieve what I'm aiming for?

Answer №1

1) It seems plausible.

2) No. Just get it done.

My Plan of Action

I would establish a blog postPagination state to store pagination data separately from entities. Then, I would implement a BlogPaginate action to modify its state in the reducer function.

{
   {
        sort: 'date',
        filters: {
            category: 'home',
            tag: 'testTag'
        }
    },
    page: 1
}

I would set up an effect to listen for router actions and match the relevant ones (such as url /blog/*) with appropriate search filters to trigger the BlogPaginate action, leading to a service call.

Enhancing Entity Caching

By caching entities, navigating back to previously viewed pages would be smoother. Depending on the frequency of content updates, I would decide whether to dispatch an action or utilize the cached value.

Next step would be to incorporate the following to the postPagination state:

{
   pageContents: {
      // mapping of page to entity ids
      1: [1,8,222]
   }
   {
        sort: 'date',
        filters: {
            category: 'home',
            tag: 'testTag'
        }
    },
    currentPage: 1,
    totalPages: 10
}
  • Whenever pagination filters / sort changes in BlogPaginate reducer, I would clear pageContents.
  • If the pagination response's totalPages changes in BlogPaginateSuccess reducer, I would clear other pageContents pages.
  • Within BlogPaginateSuccess reducer, I would add/update new entities in blog posts and map their ids in pageContents. Keep in mind that reducers can react to any action.
  • I would also develop a selector that combines postPagination.currentPage, postPagination.pageContents, and post.entities into an array of blog post entities.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Trouble getting search filter to function properly on an array of objects in a Vue JavaScript application

Can someone help me with integrating this code into my project? Here is the code I am referencing: http://jsfiddle.net/dkmmhf5y/701/ This snippet shows my JavaScript file, please disregard the 'test' data var app = new Vue ( { el: &apos ...

Customize the style based on the state using styled components

I am currently working with a function component that looks like this: const Navbar = ({setNav, nav}) => { const [justify, setJustify] = useState('space-around') //get localStorage const user = JSON.parse(localStorage.getItem('user& ...

Having trouble setting up an input tag to successfully submit the form and trigger the opening of a BootStrap Modal

Is there a way for me to submit a form to my servlet and open a BootStrap Modal simultaneously using an input tag in my .jsp file? I've tried setting the input tag type to "button" but then I can't submit the form. And when I set it to "submit", ...

Setting up Vue CLI 4 with ESLint, TypeScript, Stylelint for SCSS, and Airbnb rules in the VS Code editor with automatic fixes on save

After struggling with configuring Vue CLI 4 with ESLint, Prettier, Airbnb rules, TypeScript, and Vetur, I found myself at a crossroads. The challenges continued to mount as the nature of the problem evolved from my previous attempts.: How to configure Vue ...

How do I retrieve the content within this HTML element using JavaScript based on its ID?

Is there a way to extract the string from this specific HTML element using JavaScript? The element has an id of recItemString_GPLA\|input, and within it, there is a string containing "qty" that I need to retrieve. Upon inspection of the element, the f ...

Date Range Selection Widget malfunctioning when used within a popup modal

Having trouble with integrating the rsuite daterangepicker and antd's daterangepicker into a React Material UI Dialog/Modal. The date picker popup seems to either not show up or appear outside of the modal window. Take a look at the image below: Clic ...

"Unexpected outcome: Angular's HTTP request for a JSON file yields an undefined

Learning Angular has been a challenging experience for me. I am currently working on reading a json file into a chart on my main app page to visualize temperature data from my PI. Despite trying various methods found online, I have not been successful so f ...

Multiple buttons in a single field

I am attempting to replace a Dropdown list with a series of buttons that will streamline the choices previously displayed by the dropdown list. Specifically, we are using graphic png files for the types of buttons. We experimented with checkboxing and ra ...

Please proceed with submitting your choices in the order that you have selected

My goal is to submit options from a dropdown list in the order they are selected, rather than in the order they appear in the list. How can I achieve this? Here is the HTML code for the dropdown: < select style = "padding: 1em;" name = "skills" multi ...

Exploring the file attributes within nw.js

I'm in the process of developing a native application using nw.js. I have included the following code snippet: <input id="fileDialog" type="file" accept=".pdf,.epub" multiple/><a id="add" href="#">Add</a> Below is my JavaScript cod ...

Difficulty encountered when attempting to extract a username with multiple spaces using the .split() method in Discord.js with NodeJS

Currently, I am enhancing a feature in my Discord Bot that fetches the League of Legends statistics of a player by using the command !lolid [enter_username_here] in a Discord chat room. The function works smoothly for usernames with just one word; however, ...

Creating a dynamic background color that pulses with animation

I recently created a script to animate the menu li element when hovering over the corresponding a element. Everything is functioning as expected, but now I'm looking to enhance the effect by having it continue as long as the mouse remains over the a e ...

Adding local JavaScript to a Vue component is a great way to enhance its functionality

I am currently working on integrating a homepage concept (Home.vue) into my project. The design is based on a template that I purchased, which includes CSS, HTML files, and custom JavaScript. While most of the CSS has been successfully imported, I am havin ...

Display various v-dialog boxes with distinct contents in a vue.js environment

Hello there! I am currently working on customizing a Vue.js template and I have encountered an issue with displaying dynamic v-dialogs using a looping statement. Currently, the dialog shows all at once instead of individually. Here is the structure of my ...

In Javascript, the difference between defining a variable using "this.varName" and "var varName" lies in the scope of the variable

Excuse my JS ignorance, but here's a question: In JS, I've noticed functions that define variables inside them like this: function functionName(){ this.something = ""; }; I'm wondering if something is considered a local variable. W ...

Determine if a div contains an svg element with JavaScript

My question involves a div containing a question mark and some SVG elements. Here is the initial setup: <div id="mydiv">?</div> When validating a form submission in my code, I check if the div text contains a question mark like this: const f ...

problem encountered while attempting to transmit data to multer in React

I was attempting to upload an image to the backend using Multer. I have reviewed the backend code multiple times and it appears to be correct. Could there be an issue with my front-end code? Here is a POST code snippet: const response = await fetch(' ...

The Katura video is loading properly, yet it is rotating instead of playing

I am working on a web application that involves playing videos from Kaltura platform and then loading the link on an iOS webview. <html> <body> <div id="myEmbedTarget" style="width:400px;height:330px;"></div> ...

Changing Marker Color in Google Maps API

There are multiple Google Maps Markers colors based on certain conditions being TRUE or not. In addition, these Markers will change color when the mouse hovers over a division (a1,a2..ax). I want the Markers to revert back to their original color when th ...

I am experiencing an issue where the result is not appearing on the input tag within my

<script> <form action="do-add-cek.php" id="myForm" method="post" enctype="multipart/form-data"> <div class="form-group"> <label> ...