Unwanted Page Reloading in SQLite3 with Node.js and Fetch API

Understanding the Unwanted Page Reloading Behavior

The core issue revolves around an unwanted page reloading behavior that occurs when performing database operations (INSERT or DELETE) in an SQLite3 database via a Node.js backend, triggered by a button click in the frontend. The frontend uses the Fetch API to communicate with the backend, and despite attempts to prevent the default behavior of the button click using event.preventDefault(), the page continues to reload. This behavior disrupts the user experience and indicates a misalignment between the frontend and backend interaction.

The frontend code includes a button that, when clicked, sends a request to the backend to either add or remove a game from a collection stored in an SQLite3 database. The backend processes this request, performs the necessary database operation, and sends a response back to the frontend. However, the page reloads immediately after the operation, which is not the intended behavior.

Exploring the Causes of Page Reloading

The unwanted page reloading can be attributed to several potential causes, each of which needs to be examined in detail.

1. Default Behavior of HTML Elements: The button element in HTML has a default behavior that can cause a page reload when clicked, especially if it is part of a form or if the JavaScript code does not explicitly prevent this behavior. In this case, the button is not part of a form, but the default behavior might still be triggered if the event is not properly handled.

2. Event Propagation and Bubbling: Event propagation refers to the way events travel through the DOM tree. When an event is triggered on an element, it can bubble up to its parent elements, potentially triggering event handlers on those elements. If a parent element has a default behavior that causes a page reload, this could be the source of the issue.

3. Fetch API and Asynchronous Operations: The Fetch API is used to send asynchronous requests to the backend. However, if the response from the backend is not handled correctly, or if there is a mismatch between the expected and actual behavior of the Fetch API, this could lead to unintended consequences such as page reloading.

4. Backend Response Handling: The backend sends a JSON response after performing the database operation. If the frontend does not handle this response correctly, or if there is an error in the backend code that causes an unexpected response, this could trigger a page reload.

5. Browser-Specific Behavior: Different browsers may handle events and Fetch API requests differently. It is possible that the issue is specific to a particular browser or version, and may not occur in others.

Detailed Troubleshooting Steps, Solutions, and Fixes

To resolve the unwanted page reloading issue, a systematic approach is required. The following steps outline the process of identifying and fixing the problem.

1. Ensuring Proper Event Handling in the Frontend:

The first step is to ensure that the button click event is properly handled in the frontend. The event.preventDefault() method is used to prevent the default behavior of the button, but it may not be sufficient on its own. The return false statement can be added to ensure that the event does not propagate further.

gameButton.addEventListener("click", (e) => {
    e.preventDefault();
    fetch(`http://localhost:3000/ajoutsuppr?gameID=${gameID}`)
        .then(resp => resp.json())
        .then(data => {
            if(data.result === false){
                console.log("Was not on list, added")
            } else {
                console.log("Was on list, deleted")
            }
        })
        .catch(error => {
            console.log('Error when request :', error);
        });
    return false;
});

Additionally, the e.stopPropagation() method can be used to prevent the event from bubbling up to parent elements, which might have their own event handlers that could cause a page reload.

gameButton.addEventListener("click", (e) => {
    e.preventDefault();
    e.stopPropagation();
    fetch(`http://localhost:3000/ajoutsuppr?gameID=${gameID}`)
        .then(resp => resp.json())
        .then(data => {
            if(data.result === false){
                console.log("Was not on list, added")
            } else {
                console.log("Was on list, deleted")
            }
        })
        .catch(error => {
            console.log('Error when request :', error);
        });
    return false;
});

2. Verifying the Backend Response Handling:

The backend code should be reviewed to ensure that it is sending the correct response and that there are no errors in the database operations. The response should be a JSON object with a result property that indicates whether the game was added or removed from the list.

app.get('/ajoutsuppr', (req, res) => {
    const gameID = req.query.gameID; // Recover game ID
    db.get(`SELECT * FROM gamelist WHERE id = ?`, [gameID], (err, row) => {
        if (err) {
            console.error('Error :', err.message);
            res.status(500).json({error: 'Database error'});
        } else {
            if (row) {
                db.run(`DELETE FROM gamelist WHERE id = ?`, [gameID], (err) => {
                    if (err) {
                        console.error("Error during deleting id from database: ", err.message);
                        res.status(500).json({error: 'Database error'});
                    } else {
                        res.json({result: true}); //If game was in the list, then delete
                    }
                });
            } else {
                db.run(`INSERT INTO gamelist VALUES (?,?)`, [gameID, Date.now()], (err) => {
                    if (err) {
                        console.error("Error during inserting id to database: ", err.message);
                        res.status(500).json({error: 'Database error'});
                    } else {
                        res.json({result: false}); //else, add it
                    }
                });
            }
        }
    });
});

3. Debugging the Fetch API Request:

The Fetch API request should be debugged to ensure that it is being sent correctly and that the response is being handled properly. This can be done by adding console logs at various stages of the request and response handling.

gameButton.addEventListener("click", (e) => {
    e.preventDefault();
    e.stopPropagation();
    console.log('Fetch request initiated');
    fetch(`http://localhost:3000/ajoutsuppr?gameID=${gameID}`)
        .then(resp => {
            console.log('Response received:', resp);
            return resp.json();
        })
        .then(data => {
            console.log('Data received:', data);
            if(data.result === false){
                console.log("Was not on list, added")
            } else {
                console.log("Was on list, deleted")
            }
        })
        .catch(error => {
            console.log('Error when request :', error);
        });
    return false;
});

4. Checking for Browser-Specific Issues:

The issue should be tested in different browsers to determine if it is specific to a particular browser. If the issue is browser-specific, it may be necessary to implement browser-specific fixes or workarounds.

5. Reviewing the HTML Structure:

The HTML structure should be reviewed to ensure that there are no elements or attributes that could be causing the page to reload. For example, if the button is inside a form, the form’s default behavior could be causing the page to reload.

<div class="game-footer">
  <div class="button-add-rem">
    <button wii-game-button></button>
  </div>
</div>

In this case, the button is not inside a form, so this is not the cause of the issue. However, it is still important to ensure that there are no other elements or attributes that could be causing the page to reload.

6. Implementing a Fallback Mechanism:

If the issue persists despite the above steps, a fallback mechanism can be implemented to prevent the page from reloading. This could involve using a different method to handle the button click, such as using an anchor tag with a href attribute set to javascript:void(0) instead of a button.

<div class="game-footer">
  <div class="button-add-rem">
    <a href="javascript:void(0)" wii-game-button></a>
  </div>
</div>

7. Using a Different Event Handling Approach:

If the issue is related to event propagation or bubbling, a different event handling approach can be used. For example, the event can be handled at the document level instead of the button level, and the event target can be checked to ensure that the correct element is being handled.

document.addEventListener("click", (e) => {
    if (e.target.hasAttribute('wii-game-button')) {
        e.preventDefault();
        e.stopPropagation();
        console.log('Fetch request initiated');
        fetch(`http://localhost:3000/ajoutsuppr?gameID=${gameID}`)
            .then(resp => {
                console.log('Response received:', resp);
                return resp.json();
            })
            .then(data => {
                console.log('Data received:', data);
                if(data.result === false){
                    console.log("Was not on list, added")
                } else {
                    console.log("Was on list, deleted")
                }
            })
            .catch(error => {
                console.log('Error when request :', error);
            });
        return false;
    }
});

8. Reviewing the Server-Side Code for Potential Issues:

The server-side code should be reviewed to ensure that there are no issues that could be causing the page to reload. For example, if the server is sending a redirect response instead of a JSON response, this could cause the page to reload.

app.get('/ajoutsuppr', (req, res) => {
    const gameID = req.query.gameID; // Recover game ID
    db.get(`SELECT * FROM gamelist WHERE id = ?`, [gameID], (err, row) => {
        if (err) {
            console.error('Error :', err.message);
            res.status(500).json({error: 'Database error'});
        } else {
            if (row) {
                db.run(`DELETE FROM gamelist WHERE id = ?`, [gameID], (err) => {
                    if (err) {
                        console.error("Error during deleting id from database: ", err.message);
                        res.status(500).json({error: 'Database error'});
                    } else {
                        res.json({result: true}); //If game was in the list, then delete
                    }
                });
            } else {
                db.run(`INSERT INTO gamelist VALUES (?,?)`, [gameID, Date.now()], (err) => {
                    if (err) {
                        console.error("Error during inserting id to database: ", err.message);
                        res.status(500).json({error: 'Database error'});
                    } else {
                        res.json({result: false}); //else, add it
                    }
                });
            }
        }
    });
});

9. Ensuring Proper Error Handling:

Proper error handling should be implemented in both the frontend and backend to ensure that any errors are caught and handled appropriately. This includes handling network errors, database errors, and any other potential issues that could arise.

gameButton.addEventListener("click", (e) => {
    e.preventDefault();
    e.stopPropagation();
    console.log('Fetch request initiated');
    fetch(`http://localhost:3000/ajoutsuppr?gameID=${gameID}`)
        .then(resp => {
            if (!resp.ok) {
                throw new Error('Network response was not ok');
            }
            console.log('Response received:', resp);
            return resp.json();
        })
        .then(data => {
            console.log('Data received:', data);
            if(data.result === false){
                console.log("Was not on list, added")
            } else {
                console.log("Was on list, deleted")
            }
        })
        .catch(error => {
            console.log('Error when request :', error);
        });
    return false;
});

10. Testing and Validation:

Finally, the solution should be thoroughly tested to ensure that the unwanted page reloading behavior has been resolved. This includes testing in different browsers, with different network conditions, and with different types of data to ensure that the solution is robust and reliable.

By following these steps, the unwanted page reloading issue can be systematically identified and resolved, ensuring a smooth and seamless user experience.

Related Guides

Leave a Reply

Your email address will not be published. Required fields are marked *