From 56ec181898c2dd9be30af028a2f76832ce708864 Mon Sep 17 00:00:00 2001 From: Chandrabhatta Sriram Date: Mon, 10 Aug 2020 12:20:59 +0530 Subject: [PATCH] De-allocating Previously Allocated Interceptors to different respective Components --- README.md | 1 + src/App.js | 21 ++++++- .../BurgerBuilder/BurgerBuilder.component.jsx | 2 +- .../withErrorHandler.closureHOC.jsx | 60 ++++++++++--------- 4 files changed, 53 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index ba91d21..bc9a371 100644 --- a/README.md +++ b/README.md @@ -64,3 +64,4 @@ Firebase Common API Endpoint: 4. Displaying a **[Spinner](https://projects.lukehaas.me/css-loaders/)** while sending a POST Request: [Commit Details](https://github.com/Ch-sriram/burger-builder/commit/2067df848d89f1b97b5d3564215b648d398468e0) 5. Handling Errors Globally using the `` Component inside the `` Closure HOC: [Commit Details](https://github.com/Ch-sriram/burger-builder/commit/74552c827692cadf1ef419214f360494ad350d81) 6. Retrieving Data from the **[Firebase Backend](https://burger-builder-ram.firebaseio.com/ingredients)** & Resetting Error Handler inside `withErrorHandler` Closure HOC inside the `constructor()` lifecycle method: [Commit Details](https://github.com/Ch-sriram/burger-builder/commit/25931159b2254abff5398b69b3ef1d9d877a5498) +7. De-allocating Previously Allocated Interceptors to different respective Components: [Commit Details]() diff --git a/src/App.js b/src/App.js index fdb0c0f..7e7666c 100644 --- a/src/App.js +++ b/src/App.js @@ -5,12 +5,31 @@ import React, { Component } from 'react'; import Layout from './components/Layout/Layout.component'; import BurgerBuilder from './containers/BurgerBuilder/BurgerBuilder.component'; +/** + * For the time being, we will just test the legibility of the + * statement: + * `axios.interceptors.request/response.eject(axiosInstance);` + * and see to it whether it will be called after the + * BurgerBuilder Component is unmounted. For that, we will just + * maintain a fake state inside the App component, to un-show + * the component depending on some condition. + */ + class App extends Component { + state = { show: true, }; + + componentDidMount() { + console.log("[App.js] componentDidMount..."); + setTimeout(() => { + this.setState({ show: false }); + }, 5000); + } + render() { return (
- + {this.state.show ? : null}
); diff --git a/src/containers/BurgerBuilder/BurgerBuilder.component.jsx b/src/containers/BurgerBuilder/BurgerBuilder.component.jsx index ee4e408..0953b18 100644 --- a/src/containers/BurgerBuilder/BurgerBuilder.component.jsx +++ b/src/containers/BurgerBuilder/BurgerBuilder.component.jsx @@ -66,7 +66,7 @@ class BurgerBuilder extends Component { */ // NOTE that `.json` is omitted to introduce an error deliberately - axios.get("https://burger-builder-ram.firebaseio.com/ingredients") + axios.get("https://burger-builder-ram.firebaseio.com/ingredients.json") .then(response => { this.setState({ ingredients: response.data }, () => { diff --git a/src/hoc/withErrorHandler/withErrorHandler.closureHOC.jsx b/src/hoc/withErrorHandler/withErrorHandler.closureHOC.jsx index 4db2b68..8137232 100644 --- a/src/hoc/withErrorHandler/withErrorHandler.closureHOC.jsx +++ b/src/hoc/withErrorHandler/withErrorHandler.closureHOC.jsx @@ -5,20 +5,41 @@ import React, { Component } from 'react'; import Modal from '../../components/UI/Modal/Modal.component'; import Aux from '../Auxiliary/Auxiliary.hoc'; +/** + * This withErrorHandler Closure HOC can be wrapped around any + * kind of a component and we can use this HOC as a general + * error handler. + * + * And so, whenever we wrap other components with this HOC, + * i.e., withErrorHandler Closure HOC, what we are doing is, + * (assume that we are using the same axios instance) we are + * creating and attaching multiple interceptors to the same + * axios instance. + * + * These interceptors create memory leaks when they're not + * properly released, and so, the releasing of these + * request/response interceptor instances have to be done by + * the programmer who's programming the react app manually + * inside the componentWillUnmount() lifecycle method using + * the axios.interceptors.request/response.eject(instance); + */ + const withErrorHandler = (WrappedComponent, axios) => { return class extends Component { constructor(props) { super(props); this.state = { error: null, }; - axios.interceptors.request.use(req => { + // We will save the interceptor instance in the state: + + this.requestInterceptor = axios.interceptors.request.use(req => { // we want to get rid of any previous errors whenever // we send our request this.setState({ error: null }); return req; }); - axios.interceptors.response.use(res => res, error => { + this.responseInterceptor = axios.interceptors.response.use(res => res, error => { // after getting the response, if there's an error, // we'll simply handle it as follows: this.setState({ error: error }); @@ -27,34 +48,15 @@ const withErrorHandler = (WrappedComponent, axios) => { ); } + componentDidMount() { + console.log("[withErrorHandler.closureHOC.jsx] componentDidMount...", this.requestInterceptor, this.responseInterceptor); + } - /** - * Now, componentDidMount() is only called once the child - * components are rendered, but whenever an error occurs, - * we need it to be handled even if the child components - * are going to render. And for that, the better way of - * handling errors during axios requests/responses will - * be inside the componentWillUpdate() lifecycle method, - * and as it is deprecated now, we can handle the axios - * related errors inside the constructor() lifecycle hook. - * - * And so, we will comment the code below, and update the - * constructor() method as shown above. - */ - // componentDidMount() { - // axios.interceptors.request.use(req => { - // // we want to get rid of any previous errors whenever - // // we send our request - // this.setState({ error: null }); - // return req; - // }) - // axios.interceptors.response.use(res => res, error => { - // // after getting the response, if there's an error, - // // we'll simply handle it as follows: - // this.setState({ error: error }); - // return Promise.reject(error); - // }) - // } + componentWillUnmount() { + console.log("[withErrorHandler.closureHOC.jsx] componentWillUnmount...", this.requestInterceptor, this.responseInterceptor); + axios.interceptors.request.eject(this.requestInterceptor); + axios.interceptors.response.eject(this.responseInterceptor); + } errorConfirmedHandler = () => { this.setState({ error: null });