<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[The Pro Dev]]></title><description><![CDATA[Tech Journal by The Pro Dev | A Software Engineer turned into Architect, Upcoming Data Engineer | Mentors talents in offtime and holds Advisory positions in Ear]]></description><link>https://theprodev.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1673267683678/ZzU7zZtMA.png</url><title>The Pro Dev</title><link>https://theprodev.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 31 Oct 2026 01:45:55 GMT</lastBuildDate><atom:link href="https://theprodev.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a Filter in a Complex React Application]]></title><description><![CDATA[How to handle state across the concerns in the application.]]></description><link>https://theprodev.hashnode.dev/building-a-filter-in-a-complex-react-application</link><guid isPermaLink="true">https://theprodev.hashnode.dev/building-a-filter-in-a-complex-react-application</guid><category><![CDATA[React]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[hooks]]></category><category><![CDATA[Next.js]]></category><dc:creator><![CDATA[Progyan 👨🏻‍💻 | #TheProDev]]></dc:creator><pubDate>Fri, 13 Jan 2023 15:49:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1673621214441/560ab5fb-8362-4452-86ba-631d54d98d0b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Often time we have to build UIs that has filters to narrow down the content shown on the screen, The data point can be represented in tabular form or as a list whatsoever. However, as a User, it is hard to keep a track of what are the filters being applied.  </p>
<p>So quite several application renders a list of filters applied somewhere in the UI before the data part or at least within the filter component. That being said, we are not here to discuss UI challenges, but something more fundamental, states.  </p>
<p>How will you manage the state across multiple components? As it stands, the state is being consumed by at least three components, the actual list, the filter and the list of applied filters, and any change in the filter should affect all three.</p>
<h2 id="heading-the-concerns">The Concerns</h2>
<p>If we simplify the problem statement, we are left with mainly three concerns:</p>
<ol>
<li><p><strong>The Data Part:</strong> How will the Data Layer know what filters are being applied and produce results accordingly?</p>
</li>
<li><p><strong>The UI Part:</strong> How can the user know and apply one or more filters in the UI?</p>
</li>
<li><p><strong>The Store Part:</strong> How can we sync the filter information and persist throughout the lifetime of such UI?</p>
</li>
</ol>
<h2 id="heading-the-data-part">The Data Part</h2>
<p>Based on how your <em>API</em> is designed, this can be achieved in multiple ways. In our case, we will assume we have <em>Query Parameters</em> over <em>GET</em> requests. Using native <code>fetch</code> we can implement the following:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> loadUsers = <span class="hljs-function">(<span class="hljs-params">filters</span>) =&gt;</span> fetch(<span class="hljs-string">`https://api.example.com/users?<span class="hljs-subst">${<span class="hljs-keyword">new</span> URLSearchParams(filters)}</span>`</span>);
</code></pre>
<h2 id="heading-the-ui-part">The UI Part</h2>
<p>On the UI side, assuming we have the filter object, it is not much hard to pass them on to React Components and have the UI show which filters are available and which are already applied. I am keeping this part open-ended intentionally.</p>
<h2 id="heading-the-store-part">The Store Part</h2>
<p>Now that we have sorted out two of three concerns, here comes the most important part. We know if we pass our active filters to the <code>fetch</code> function we will get updated results. We also are sure that if we know the filters, we can show them in the UI.</p>
<p>Like how we have <em>Query Parameters</em> for the <em>API</em>, what about having the same for the page? After all, it is just a medium to the back-end data service!</p>
<p>So we store the filter object into the URL as Parameters post serialization. And deserialize during the render. This also gives us an edge for bookmarking and sharing preferable result sets. However, given that the URL can be modified outside the scope of the application, there needs to be validation logic as well.</p>
<p>Let's compile all of this into a reusable React hook:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { NextRouter, useRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/router"</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> Yup <span class="hljs-keyword">from</span> <span class="hljs-string">"yup"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> Lazy <span class="hljs-keyword">from</span> <span class="hljs-string">"yup/lib/Lazy"</span>;

<span class="hljs-comment">/**
 * Available Options on Validation Schema.
 */</span>
<span class="hljs-keyword">type</span> Options&lt;T <span class="hljs-keyword">extends</span> Yup.AnyObjectSchema | Lazy&lt;<span class="hljs-built_in">any</span>&gt;&gt; = Parameters&lt;
  T[<span class="hljs-string">"validateSync"</span>]
&gt;[<span class="hljs-number">1</span>];

<span class="hljs-comment">/**
 * Query Filter Result Interface.
 */</span>
<span class="hljs-keyword">type</span> QueryFilterResult&lt;T <span class="hljs-keyword">extends</span> Record&lt;<span class="hljs-built_in">string</span>, <span class="hljs-built_in">any</span>&gt;&gt; = {
  <span class="hljs-comment">/**
   * Validation error on Filter Key Value pairs.
   */</span>
  errors: Partial&lt;T&gt;;
  <span class="hljs-comment">/**
   * Filter results using one or more Parameter.
   * @param filters - A Key Value pair of Filter Names and Values.
   */</span>
  filterBy(filters: Partial&lt;T&gt;): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">void</span>&gt;;
  <span class="hljs-comment">/**
   * Key Value pair of applicable Filters.
   */</span>
  filters: T;
  <span class="hljs-comment">/**
   * Reset Filters.
   */</span>
  reset(filters?: Partial&lt;T&gt;): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">void</span>&gt;;
};

<span class="hljs-comment">/**
 * Mutable Ref Object to hold current values of Filter and Validation Errors.
 */</span>
<span class="hljs-keyword">type</span> QueryFilterRef&lt;T&gt; = {
  <span class="hljs-comment">/**
   * Validation error on Filter Key Value pairs.
   */</span>
  errors: Partial&lt;T&gt;;
  <span class="hljs-comment">/**
   * Key Value pair of applicable Filters.
   */</span>
  values: T;
};

<span class="hljs-comment">/**
 * Query Filter Interface.
 */</span>
<span class="hljs-keyword">type</span> QueryFilter = &lt;T <span class="hljs-keyword">extends</span> Yup.AnyObjectSchema | Lazy&lt;<span class="hljs-built_in">any</span>&gt;&gt;<span class="hljs-function">(<span class="hljs-params">
  /** Yup Schema <span class="hljs-keyword">of</span> the Query Filters. */
  schema: T,
  /** Additional Schema Options <span class="hljs-keyword">for</span> Validation. */
  options?: Options&lt;T&gt;,
</span>) =&gt;</span> QueryFilterResult&lt;Yup.InferType&lt;T&gt;&gt;;

<span class="hljs-comment">/**
 * Push onto History Stack with Query Parameters.
 * @param router - Next Router Instance.
 * @param queryParams - Query Parameters.
 */</span>
<span class="hljs-keyword">const</span> pushStateWithQuery = &lt;T <span class="hljs-keyword">extends</span> Record&lt;<span class="hljs-built_in">string</span>, <span class="hljs-built_in">any</span>&gt;&gt;<span class="hljs-function">(<span class="hljs-params">
  router: NextRouter,
  queryParams: T,
</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> url = <span class="hljs-string">`<span class="hljs-subst">${router.pathname}</span>?<span class="hljs-subst">${<span class="hljs-keyword">new</span> URLSearchParams(queryParams)}</span>`</span>;
  <span class="hljs-keyword">return</span> router.push(url, <span class="hljs-literal">undefined</span>, { scroll: <span class="hljs-literal">false</span>, shallow: <span class="hljs-literal">true</span> });
};

<span class="hljs-comment">/**
 * Transforms Yup Validation Error to Serialsed Schema.
 * @param error - Yup Error Object.
 * @returns Seralised Error Object.
 */</span>
<span class="hljs-keyword">const</span> parseYupError = <span class="hljs-function">(<span class="hljs-params">error: Yup.ValidationError</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (!error.inner.length) {
    <span class="hljs-keyword">return</span> {
      [error.path!]: error.errors[<span class="hljs-number">0</span>],
    };
  }

  <span class="hljs-keyword">return</span> (error.inner || []).reduce&lt;Record&lt;<span class="hljs-built_in">string</span>, <span class="hljs-built_in">string</span>&gt;&gt;(
    <span class="hljs-function">(<span class="hljs-params">previous, error</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (!previous[error.path!]) {
        previous[error.path!] = error.message;
      }

      <span class="hljs-keyword">return</span> previous;
    },
    {},
  );
};

<span class="hljs-comment">/**
 * Default Parameters for Schema Validation Options.
 */</span>
<span class="hljs-keyword">const</span> BaseSchemaOptions: Partial&lt;Options&lt;Yup.AnyObjectSchema | Lazy&lt;<span class="hljs-built_in">any</span>&gt;&gt;&gt; = {
  abortEarly: <span class="hljs-literal">true</span>,
  stripUnknown: <span class="hljs-literal">true</span>,
} <span class="hljs-keyword">as</span> <span class="hljs-keyword">const</span>;

<span class="hljs-comment">/**
 * Validates a given object against provided Schema and Schema Options.
 * @param object - Instance of Object that requires Validation.
 * @param schema - Schema to Validate against.
 * @param options - Schema Validation Options.
 * @returns An Object with Parsed Values and Validation Errors.
 */</span>
<span class="hljs-keyword">const</span> validateYupSchema = &lt;
  T <span class="hljs-keyword">extends</span> Yup.AnyObjectSchema | Lazy&lt;<span class="hljs-built_in">any</span>&gt;,
  O <span class="hljs-keyword">extends</span> Record&lt;<span class="hljs-built_in">string</span>, <span class="hljs-built_in">any</span>&gt;,
&gt;(
  <span class="hljs-built_in">object</span>: O,
  schema: T,
  options: Options&lt;T&gt;,
): QueryFilterRef&lt;Yup.InferType&lt;T&gt;&gt; =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">return</span> {
      values: schema.validateSync(
        <span class="hljs-built_in">object</span>,
        <span class="hljs-built_in">Object</span>.assign(BaseSchemaOptions, options),
      ),
      errors: {},
    };
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">return</span> {
      values: {},
      errors: parseYupError(error <span class="hljs-keyword">as</span> Yup.ValidationError) <span class="hljs-keyword">as</span> Partial&lt;
        Yup.InferType&lt;T&gt;
      &gt;,
    };
  }
};

<span class="hljs-comment">/**
 * Create Filters out of Query Parameters in current Page.
 * @param schema - Yup Schema of the Query Filters.
 * @param options - Additional Schema Options for Validation.
 * @returns Parsed Filters, callback to update Filters and Error Object in case of validation error.
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> useQueryFilter: QueryFilter = <span class="hljs-function">(<span class="hljs-params">schema, options</span>) =&gt;</span> {
  <span class="hljs-keyword">type</span> Schema = Yup.InferType&lt;<span class="hljs-keyword">typeof</span> schema&gt;;

  <span class="hljs-keyword">const</span> router = useRouter();

  <span class="hljs-keyword">const</span> filtersRef = React.useRef&lt;QueryFilterRef&lt;Schema&gt;&gt;({
    values: {},
    errors: {},
  });

  filtersRef.current = validateYupSchema(router.query, schema, options);

  <span class="hljs-comment">/** Cleanup Query Parameters */</span>
  useInsertionEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { values: filters } = filtersRef.current;
    pushStateWithQuery(router, filters);
  }, []);

  <span class="hljs-keyword">const</span> filterBy = React.useCallback(<span class="hljs-keyword">async</span> (filters: Partial&lt;Schema&gt;) =&gt; {
    <span class="hljs-comment">/** This avoids Stale Closure problem by using Mutable Ref instance. */</span>
    <span class="hljs-keyword">const</span> { values: _filters } = filtersRef.current;
    <span class="hljs-keyword">const</span> nextFilters = {
      ..._filters,
      ...filters,
    };

    <span class="hljs-keyword">const</span> pushStatePromise = pushStateWithQuery(router, nextFilters);

    <span class="hljs-comment">/** This ensures consecutive call of `filterBy` does not reset earlier filters. */</span>
    filtersRef.current = {
      errors: {},
      values: nextFilters,
    };

    <span class="hljs-comment">/** This is useful for chaining promises in consumer component or hook. */</span>
    <span class="hljs-keyword">await</span> pushStatePromise;
  });

  <span class="hljs-keyword">const</span> reset = React.useCallback(<span class="hljs-keyword">async</span> (filters: Partial&lt;Schema&gt; = {}) =&gt; {
    <span class="hljs-keyword">const</span> pushStatePromise = pushStateWithQuery(router, filters);

    <span class="hljs-comment">/** This ensures subsequent call of `filterBy` does not reuse earlier filters. */</span>
    filtersRef.current = {
      errors: {},
      values: filters,
    };

    <span class="hljs-comment">/** This is useful for chaining promises in consumer component or hook. */</span>
    <span class="hljs-keyword">await</span> pushStatePromise;
  });

  <span class="hljs-keyword">const</span> { values: filters, errors } = filtersRef.current;

  <span class="hljs-keyword">return</span> {
    errors,
    filterBy,
    filters,
    reset,
  };
};
</code></pre>
<p>That is it. Now you have a React hook managing your state, and on the consumer side, you can use the current state to manage and update the result set and show them in your UI.</p>
]]></content:encoded></item><item><title><![CDATA[I had to integrate few React components in a Django View using jQuery: A Journey]]></title><description><![CDATA[How did I load my React Components into existing jQuery based UI rendered by Django on Server at Interview Kickstart]]></description><link>https://theprodev.hashnode.dev/rendering-react-component-in-django-jquery-ui</link><guid isPermaLink="true">https://theprodev.hashnode.dev/rendering-react-component-in-django-jquery-ui</guid><category><![CDATA[Frontend Development]]></category><category><![CDATA[React]]></category><category><![CDATA[Django]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[technology]]></category><dc:creator><![CDATA[Progyan 👨🏻‍💻 | #TheProDev]]></dc:creator><pubDate>Mon, 09 Jan 2023 12:25:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1673245430375/a73ea775-7afe-4a92-a1c9-fb01f1ccc488.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A small journey into my Tech World filled with bizarre experiences. One such instance that comes to mind is when I had to make some enhancements to an existing UI that was written earlier. The older Tech Stack was Django-based SSR (using View Templating) with jQuery in the browser. However, the enhancement planned was based on React, as the library, we will be composing on top of was built in React and we were already in the middle of a Tech Stack migration for the front-end. On the other hand, the whole UI system of the existing one was quite heavy and would require significant <em>person-hour</em> to completely migrate to React. So we made a decision that we will build all enhancements in React while keeping the older UI intact and just extensible.</p>
<p><em>TLDR;</em> Experienced React developers can skip directly to the <a target="_blank" href="https://theprodev.hashnode.dev/rendering-react-component-in-django-jquery-ui?showSharer=true#heading-lets-get-started">Let's Get Started</a> chapter.</p>
<h2 id="heading-how-react-works-in-browser">How React Works in Browser</h2>
<p>Before we get started with the nitty-gritty implementation details of the topic. Let us take a moment and understand how the React libraries work under the hood to build the UI we declared in our codebase.</p>
<p>In our codebase, a React component might look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> HelloWorldComponent = <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>;
</code></pre>
<p>And we might be rendering this into UI as follows, assuming we have an empty <em>div</em> with the id <em>"app"</em>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ReactDOMClient <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;

<span class="hljs-keyword">import</span> { HelloWorldComponent } <span class="hljs-keyword">from</span> <span class="hljs-string">"./HelloWorld"</span>;

<span class="hljs-keyword">const</span> appContainer = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"app"</span>);
<span class="hljs-keyword">const</span> appRoot = ReactDOMClient.createRoot(appContainer);

appRoot.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">HelloWorldComponent</span> /&gt;</span></span>);
</code></pre>
<p>Now underneath the hood, React will create the required element tree and append it to the aforesaid <em>div</em>. The purpose of <em>ReactDOM</em> here is to reflect all our declarative UI mapping into actual DOM elements.</p>
<h2 id="heading-module-bundlers">Module Bundlers</h2>
<p>It would not be an overstatement to say front-end state of art applications as we see them today might not have existed if not for high-end module bundlers like Webpack, Rollup, Turbopack, Vite etc. The core purpose of these tools is to convert a set of source files from the developer workspace into a couple of executable files for the staging/production environment, e.g., a browser.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0dDhpCqD--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nwmf2clu7cew1lgdsltf.png" alt="Module Bundlers" /></p>
<p><img src="https://miro.medium.com/max/1400/1*dbLSMmG_9YNaVRyn30YKBQ.png" alt="Webpack Documentation - Image: https://webpack.js.org" /></p>
<p>One of the key file these module bundlers generate is the Manifest file. This file is responsible to provide metadata to the runtime so that the runtime can load the entry point and dependencies as they are needed. Webpack generates a file called <em>asset-manifest.json</em> which holds information on the mapping between source files and runtime assets and a list of entry points.</p>
<h2 id="heading-lets-get-started">Let's Get Started</h2>
<p>We start our journey by creating a factory function that will be exposed to the outside world. For the sake of simplicity, let us assume we want to make this function available in the global scope. This pattern can be improved using custom loaders, but we can skip it for the time being.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Component, ComponentProps } <span class="hljs-keyword">from</span> <span class="hljs-string">"components"</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> ReactDOMClient <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;

<span class="hljs-comment">/**
 * Factory Method for React Component.
 * @param container DOM Container to render React Component.
 * @param props Incoming Props for React Component.
 * @returns Object with a handler to unmount React Component from the DOM.
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ComponentFactory = (container: Element, <span class="hljs-attr">props</span>: ComponentProps): <span class="hljs-function"><span class="hljs-params">VoidFunction</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> root = ReactDOMClient.createRoot(container, { <span class="hljs-attr">identifierPrefix</span>: <span class="hljs-string">"react"</span> });
  root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...props</span>} /&gt;</span></span>);

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">destroy</span>: <span class="hljs-function">() =&gt;</span> root.unmount(),
  };
};
</code></pre>
<p>Once went through the build pipeline, this yields <code>main_[contenthash].js</code> file which would be the entry point of our application, considering everything inside the <em>Component</em> is valid.</p>
<h2 id="heading-the-middleware-house">The Middleware House</h2>
<p>Now we have two problems at hand, one is to tell Django that we have to load runtime assets generated by our module bundler, Webpack in this case; and invoke the factory function from the current system with proper parameters to create the UI. Let's take the first one for a spin.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Standard library imports.</span>
<span class="hljs-keyword">import</span> json
<span class="hljs-keyword">import</span> re
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Any, Callable, Dict, List, Union

<span class="hljs-comment"># Valid Keys in Asset Manifest JSON Type Alias.</span>
AssetManifestKeys = Literal[<span class="hljs-string">"entrypoints"</span>, <span class="hljs-string">"files"</span>]


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AssetManifest</span>:</span>
    <span class="hljs-string">"""
    Asset Manifest Class
    """</span>

    files: Dict[str, str]
    <span class="hljs-string">"""
    Mapping between Original Filenames and their Artifact Name (appended by content-hash for caching purposes).
    """</span>
    entrypoints: List[str]
    <span class="hljs-string">"""
    List of files that needs to loaded by the Page to start Client application.
    """</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, decoded_json: Dict[AssetManifestKeys, Any]</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        <span class="hljs-string">"""
        Constructor method for Asset Manifest Class.
        """</span>
        self.entrypoints = decoded_json[<span class="hljs-string">"entrypoints"</span>]
        self.files = decoded_json[<span class="hljs-string">"files"</span>]


<span class="hljs-comment"># Default Callbale to parse JSON String.</span>
WHITESPACE = re.compile(<span class="hljs-string">r"[ \t\n\r]*"</span>, re.VERBOSE | re.MULTILINE | re.DOTALL)


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AssetManifestDecoder</span>(<span class="hljs-params">json.JSONDecoder</span>):</span>
    <span class="hljs-string">"""
    JSON Decoder Class to Parse JSON String into Asset Manifest Class instance.
    """</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decode</span>(<span class="hljs-params">self, s: str, _w: Callable[..., Any] = WHITESPACE.match</span>) -&gt; AssetManifest:</span>
        <span class="hljs-string">"""
        Return the Asset Manifest class instance of ``s`` (a ``str`` instance
        containing a JSON document).
        """</span>
        decoded_json: Dict[AssetManifestKeys, Any] = super().decode(s, _w)
        asset_manifest = AssetManifest(decoded_json)
        <span class="hljs-keyword">return</span> asset_manifest


<span class="hljs-comment"># Valid File Name/Descriptor Type Alias.</span>
StrOrBytes = Union[str, bytes]
StrOrBytesPath = Union[StrOrBytes, PathLike[str], PathLike[bytes]] OpenFile = Union[StrOrBytesPath, int]  <span class="hljs-comment"># noqa: Y026</span>


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load_asset_manifest</span>(<span class="hljs-params">filepath: OpenFile</span>) -&gt; AssetManifest:</span>
    <span class="hljs-string">"""
    Helper Function to load Module Bundler (like Webpack, Rollup etc.) generated Asset Manifest.
    """</span>
    <span class="hljs-keyword">with</span> open(filepath, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> fp:
        <span class="hljs-keyword">return</span> json.load(fp, cls=AssetManifestDecoder)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">parse_asset_manifest</span>(<span class="hljs-params">strOrBytes: StrOrBytes</span>) -&gt; AssetManifest:</span>
    <span class="hljs-string">"""
    Helper Function to parse Module Bundler (like Webpack, Rollup etc.) generated Asset Manifest.
    """</span>
    <span class="hljs-keyword">return</span> json.loads(strOrBytes, cls=AssetManifestDecoder)
</code></pre>
<p>Here we have developed our custom <em>JSON</em> Decoder that serializes a <em>JSON</em> string into an <code>AssetManifest</code> object. The function <code>parse_asset_manifest</code> can be tested in isolation for validation, however, we would be using the <code>load_asset_manifest</code> function more often. Provided we can configure the destination directory for Webpack to emit the manifest file, the actual file path can be given through environment variables.</p>
<p>Now let's create a mixin that composes this middleware and simplifies the integration process.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ReactViewMixin</span>(<span class="hljs-params">TemplateView</span>):</span>
    <span class="hljs-string">"""
    Mixin that helps loading React assets into Server-side HTML.
    This should add `react_assets` property to context data which then to be added into `&lt;script&gt;` tag.
    """</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_context_data</span>(<span class="hljs-params">self, **kwargs: Any</span>) -&gt; Dict[str, Any]:</span>
        <span class="hljs-string">"""
        Overwrite Context Data to hold static assets required to load React Component in the UI.
        """</span>
        context_data = super().get_context_data(**kwargs)
        asset_manifest = load_asset_manifest(settings.REACT_ASSET_MANIFEST_PATH)
        context_data[<span class="hljs-string">"react_assets"</span>] = asset_manifest.entrypoints
        <span class="hljs-keyword">return</span> context_data
</code></pre>
<p>Now we can simply inherit any Django View from here and it will work out of the box.</p>
<h2 id="heading-bootstrapping-in-browser">Bootstrapping in Browser</h2>
<p>First of all, we need to add <code>&lt;script&gt;</code> tags for React resources into our view templates.</p>
<pre><code class="lang-php-template"><span class="xml">{% for asset in react_assets %}
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"application/javascript"</span> <span class="hljs-attr">defer</span>=<span class="hljs-string">""</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/{{ asset }}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
{% endfor %}</span>
</code></pre>
<p>I believe here on, figuring out the rest is quite easy. We will have an empty <em>div</em> and will pick that element once the document is ready and invoke the factory function with proper parameters.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"id_react_app"</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
$(<span class="hljs-built_in">document</span>).ready(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> $container = $(<span class="hljs-string">"#id_react_app"</span>);
  <span class="hljs-keyword">var</span> container  = $container.get(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">var</span> ref = ComponentFactory(container, {
    <span class="hljs-attr">onMount</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"React Component Mounted!"</span>),
  });

  $(<span class="hljs-built_in">window</span>).on(<span class="hljs-string">"beforeunload"</span>, ref.destroy());
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>So it turns out, despite sounding unorthodox, it is possible to integrate a React UI system into an existing one and could be a potential choice that saves some $$ for the business.</p>
<p><img src="https://media.tenor.com/-CSZYL3DkmYAAAAd/abhijeet-dancin-abhijeet-cid.gif" alt="Abhijeet Dancin Abhijeet Cid GIF - Abhijeet Dancin Abhijeet Cid Smile -  Discover &amp; Share GIFs" /></p>
]]></content:encoded></item></channel></rss>