<?xml-stylesheet href="/pretty-feed-v2.xsl" type="text/xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Trys Mudford's Blog</title>
    <link>https://www.trysmudford.com/tags/react/</link>
    <description>Posts, thoughts, links and photos from Trys</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 08 Jan 2025 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://www.trysmudford.com/blog/index.xml" rel="self" type="application/rss+xml"/>
    
    <item>
      <title>Testing knarly React hooks</title>
      <link>https://www.trysmudford.com/blog/testing-knarly-hooks/</link>
      <pubDate>Wed, 08 Jan 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.trysmudford.com/blog/testing-knarly-hooks/</guid>
      <description><![CDATA[
<p>Treat this post as a reminder to future me, when I&rsquo;m tearing my hair out after testing knarly hooks in React. Hooks that use: <code>useEffect</code> + <code>async/await</code> + <code>setInterval</code> + state updates = 🤯</p>
<p>Here are all the things you probably forgot to do, Trys:</p>
<ol>
<li>Use <code>renderHook</code> from <code>testing-library-test-utils</code></li>
</ol>
<p>It gives you a <code>result</code> object, as well as some very handy <code>waitFor</code> functions. These are particularly useful when the hook fires off an async function in <code>useEffect</code>.</p>
<div class="highlight"><pre class="chroma"><code class="language-js" data-lang="js"><span class="kr">const</span> <span class="p">{</span> <span class="nx">result</span><span class="p">,</span> <span class="nx">rerender</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">renderHook</span><span class="p">(</span><span class="nx">useHookYouAreTesting</span><span class="p">,</span> <span class="p">{</span> <span class="nx">initialProps</span><span class="o">:</span> <span class="p">{</span> <span class="p">...</span><span class="nx">props</span> <span class="p">}</span> <span class="p">});</span>
</code></pre></div><ol start="2">
<li>Wrap <code>act</code> around state updates</li>
</ol>
<p>Anything that causes a state update and subsequent rerender should be wrapped in <code>act</code>.</p>
<ol start="3">
<li>Use the right <code>act</code></li>
</ol>
<p><code>act</code> from <code>react-dom/test-utils</code> is different from <code>act</code> from <code>@testing-library/react</code> which is different from <code>react-test-renderer</code>. Use the right one. I don&rsquo;t know which is the right one, but one of them is 🤷</p>
<ol start="4">
<li><code>waitFor</code> is your friend</li>
</ol>
<p><code>waitFor</code> waits for an assertion to pass. It&rsquo;s handy when you&rsquo;re testing async code <code>waitForValueToChange</code> was really useful, but doesn&rsquo;t work in React 18. Use <code>waitFor</code> instead.</p>
<ol start="5">
<li><code>jest.useFakeTimers</code> is also your friend</li>
</ol>
<p>Timeouts and Intervals are a pain to test. <code>jest.useFakeTimers</code> makes them a little less painful. Use <code>jest.advanceTimersByTime</code> to move time forward. Use <code>jest.runOnlyPendingTimers</code> to run any pending timers. Use <code>jest.useRealTimers</code> to go back to the real world (pop that in an <code>afterEach</code>).</p>
<ol start="6">
<li>Group things</li>
</ol>
<p>I&rsquo;m waiting for my friend <a href="https://szympajka.com/">Szymon</a> to write a blog post on this (consider this a nudge, pal!) - he&rsquo;s come up with a beautiful pattern for testing hooks/components, so I&rsquo;ll link to that here when it&rsquo;s done.</p>
]]>
      </description>
    </item>
    
    <item>
      <title>Using &#39;use&#39; to stream deferred content</title>
      <link>https://www.trysmudford.com/blog/nextjs-use/</link>
      <pubDate>Fri, 30 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>https://www.trysmudford.com/blog/nextjs-use/</guid>
      <description><![CDATA[
<p>In the constant bid to improve page performance, I discovered <code>use</code>, an API recently shipped by React, and made available in Next.js. You&rsquo;d be forgiven for not immediately understanding its function, given the oh-so-descriptive name.</p>
<p><a href="https://react.dev/reference/react/use">use</a> lets you read the value of a promise (or context if you&rsquo;re that way inclined). It feels like a bit of syntactic sugar, to avoid writing <code>.then()</code> or <code>await</code> within your component, but I&rsquo;m sure there&rsquo;s more to it than that.</p>
<h2 id="when-is-use-useful">When is &lsquo;use&rsquo; useful?</h2>
<p><img src="/images/blog/use-carousel.jpg" alt=""></p>
<p>Take this carousel. Pretty standard stuff at the end of a product page. Definitely shouldn&rsquo;t be render-blocking, and a prime candidate for deferred loading. We could move the data request into a client-side handler and call <code>useEffect</code> to fetch the data on the client, but finding ways to avoid <code>useEffect</code> becomes a source of personal pride once you&rsquo;ve worked on a React project for any length of time. This approach has to wait for the whole page to hydrate before it can get to work loading the data.</p>
<p>Instead, we can still begin fetching the data on the server, but combine <code>&lt;Suspense&gt;</code> and <code>use</code> to handle the loading state before resolving it on the client.</p>
<h2 id="what-does-use-look-like">What does &lsquo;use&rsquo; look like?</h2>
<p>Before:</p>
<div class="highlight"><pre class="chroma"><code class="language-tsx" data-lang="tsx"><span class="kr">export</span> <span class="k">default</span> <span class="kr">async</span> <span class="kd">function</span> <span class="nx">Page() {</span>
    <span class="c1">// Wait for the data to load
</span><span class="c1"></span>    <span class="kr">const</span> <span class="nx">vehicles</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">getVehiclesFromDB</span><span class="p">();</span>

    <span class="k">return</span> <span class="p">(</span>
        <span class="p">&lt;</span><span class="nt">SimilarVehicles</span> <span class="na">vehicles</span><span class="o">=</span><span class="p">{</span><span class="nx">vehicles</span><span class="p">}</span> <span class="p">/&gt;</span>
    <span class="p">);</span>
<span class="p">}</span>

<span class="kr">export</span> <span class="kr">const</span> <span class="nx">SimilarVehicles</span>: <span class="kt">React.FC</span><span class="o">&lt;</span><span class="p">{</span>
    <span class="nx">vehicles</span>: <span class="kt">VehiclePreview</span><span class="p">[];</span>
<span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">vehicles</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">(</span>
        <span class="p">&lt;</span><span class="nt">section</span> <span class="na">className</span><span class="o">=</span><span class="p">{</span><span class="nx">cx</span><span class="p">(</span><span class="nx">styles</span><span class="p">.</span><span class="nx">section</span><span class="p">)}&gt;</span>
            <span class="p">{</span><span class="nx">vehicles</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">vehicle</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">(</span>
                <span class="p">&lt;</span><span class="nt">VehicleCard</span>
                    <span class="na">key</span><span class="o">=</span><span class="p">{</span><span class="nx">vehicle</span><span class="p">.</span><span class="nx">vehicleId</span><span class="p">}</span>
                    <span class="na">vehicle</span><span class="o">=</span><span class="p">{</span><span class="nx">vehicle</span><span class="p">}</span>
                <span class="p">/&gt;</span>
            <span class="p">))}</span>
        <span class="p">&lt;/</span><span class="nt">section</span><span class="p">&gt;</span>
    <span class="p">);</span>
<span class="p">};</span>
</code></pre></div><p>After:</p>
<div class="highlight"><pre class="chroma"><code class="language-tsx" data-lang="tsx"><span class="kr">export</span> <span class="k">default</span> <span class="kr">async</span> <span class="kd">function</span> <span class="nx">Page() {</span>
    <span class="c1">// Crack on rendering the page
</span><span class="c1"></span>    <span class="kr">const</span> <span class="nx">vehiclesPromise</span> <span class="o">=</span> <span class="nx">getVehiclesFromDB</span><span class="p">();</span>

    <span class="k">return</span> <span class="p">(</span>
        <span class="p">&lt;</span><span class="nt">Suspense</span> <span class="na">fallback</span><span class="o">=</span><span class="p">{&lt;</span><span class="nt">LoadingState</span> <span class="p">/&gt;}&gt;</span>
            <span class="p">&lt;</span><span class="nt">SimilarVehicles</span> <span class="na">vehiclesPromise</span><span class="o">=</span><span class="p">{</span><span class="nx">vehiclesPromise</span><span class="p">}</span> <span class="p">/&gt;</span>
        <span class="p">&lt;/</span><span class="nt">Suspense</span><span class="p">&gt;</span>
    <span class="p">);</span>
<span class="p">}</span>

<span class="kr">export</span> <span class="kr">const</span> <span class="nx">SimilarVehicles</span>: <span class="kt">React.FC</span><span class="o">&lt;</span><span class="p">{</span>
    <span class="nx">vehiclesPromise</span>: <span class="kt">Promise</span><span class="p">&lt;</span><span class="nt">VehiclePreview</span><span class="err">[]</span><span class="p">&gt;;</span>
<span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">vehiclesPromise</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="c1">// Resolve the promise
</span><span class="c1"></span>    <span class="kr">const</span> <span class="nx">vehicles</span> <span class="o">=</span> <span class="nx">use</span><span class="p">(</span><span class="nx">vehiclesPromise</span><span class="p">);</span>

    <span class="k">return</span> <span class="p">(</span>
        <span class="p">&lt;</span><span class="nt">section</span> <span class="na">className</span><span class="o">=</span><span class="p">{</span><span class="nx">cx</span><span class="p">(</span><span class="nx">styles</span><span class="p">.</span><span class="nx">section</span><span class="p">)}&gt;</span>
            <span class="p">{</span><span class="nx">vehicles</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">vehicle</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">(</span>
                <span class="p">&lt;</span><span class="nt">VehicleCard</span>
                    <span class="na">key</span><span class="o">=</span><span class="p">{</span><span class="nx">vehicle</span><span class="p">.</span><span class="nx">vehicleId</span><span class="p">}</span>
                    <span class="na">vehicle</span><span class="o">=</span><span class="p">{</span><span class="nx">vehicle</span><span class="p">}</span>
                <span class="p">/&gt;</span>
            <span class="p">))}</span>
        <span class="p">&lt;/</span><span class="nt">section</span><span class="p">&gt;</span>
    <span class="p">);</span>
<span class="p">};</span>
</code></pre></div><h2 id="how-does-use-work">How does &lsquo;use&rsquo; work?</h2>
<p>By continuing to call the vehicles database from the server, we&rsquo;ve kept our precious server-side secrets safe. But by omitting <code>await</code>, we can crack on with streaming the page to the user much quicker than before.</p>
<p>React pops our fallback component in place, and continues to stream the page in the background until the database call resolves. At that point, the page connection closes and the component inside <code>&lt;Suspense&gt;</code> is rendered. <code>use</code> converts the promise over to our intended data format, and the component renders as expected.</p>
<p>You can even use <code>ErrorBoundary</code> to handle promise failures. Pretty neat.</p>
<h2 id="does-use-work-without-js">Does &lsquo;use&rsquo; work without JS?</h2>
<p>Sadly not. React needs JS at runtime to swap out the loading content with the deferred content. Non-JS users will be left with the loading component for infinity. So this isn&rsquo;t appropriate for core user journey functionality, or spider-friendly content.</p>
]]>
      </description>
    </item>
    
    <item>
      <title>Next.js Server Actions</title>
      <link>https://www.trysmudford.com/blog/next-server-actions/</link>
      <pubDate>Tue, 20 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://www.trysmudford.com/blog/next-server-actions/</guid>
      <description><![CDATA[
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 1 - Slide 1.jpg"
		alt="Title slide of the talk: Lessons from using Next.js Server Actions: The good, the bad, and the plain undocumented"
		loading="lazy"
	/>
	<figcaption>
		<p>This is a (rough) transcript of a talk I gave at work at the end of last year, entitled: "Lessons from using Next.js Server Actions: The good, the bad, and the plain undocumented".</p>
		<p>We'd just launched a greenfield product that used Server Actions and this talk was an opportunity to share the approach, top tips, and gotchas that I'd learned along the way.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 1 - Slide 3.jpg"
		alt="What are server actions: Stable in Next 14"
		loading="lazy"
	/>
	<figcaption>
		<p>Server Actions were recently released to stable in Next.js 14.0.0, although they've been developed behind an experimental feature flag for a number of months.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 1 - Slide 4.jpg"
		alt="Built into React Canary"
		loading="lazy"
	/>
	<figcaption>
		<p>Although released as part of Next.js, they are built into React Canary and utilise several 'core' hooks. Although, as you might've read recently, the gap between React Canary and Vercel is hazy at best.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 1 - Slide 6.jpg"
		alt="Server actions only ever run on the server"
		loading="lazy"
	/>
	<figcaption>
		<p>But what <em>exactly</em> are they? They are asynchronous functions that <strong>only</strong> ever run on the server. Whereas you may currently write what <em>looks</em> like a server function to get some initial page state, you'll find they're regularly called by the client-side as the SPA mode of Next.js takes over.</p>
		<p>Server Actions will <strong>only</strong> run on the server, which brings a tonne of security, performance and accessibility benefits. Next.js provides the tooling to make your application continue to <em>feel</em> like it's making client-side requests, but under the hood, there's a load more native, web-standard plumbing going on.</p>
		<p>Think of them as the perfect backend-for-frontend starting point.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 1 - Slide 7.jpg"
		alt="Typically receive a FormData class"
		loading="lazy"
	/>
	<figcaption>
		<p>They typically receive a <code>FormData</code> class as an input parameter&hellip;</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 1 - Slide 8.jpg"
		alt="Return object/redirects"
		loading="lazy"
	/>
	<figcaption>
		<p>&hellip;and they usually return serializable objects or redirects.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 1 - Slide 9.jpg"
		alt="The three methods to invoke server actions:"
		loading="lazy"
	/>
	<figcaption>
		<p>They can be invoked in three ways:</p>
		<ul>
			<li>An <code>action</code> attribute on a <code>form</code></li>
			<li>A <code>formAction</code> attribute on a <code>button</code></li>
			<li>Within a <code>startTransition</code> method, returned by the new <code>useTransition</code> hook</li>
		</ul>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 1 - Slide 10.jpg"
		alt="Server Components + Server Actions"
		loading="lazy"
	/>
	<figcaption>
		<p>They play really nicely with Server Components. When understood and used correctly, they beautifully separate the concerns of your HTML rendering path, client-side interactivity, and API requests. They encourage the mindset of responsible server-side rendering.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 2.jpg"
		alt="Example no. 1 - the cookie bar"
		loading="lazy"
	/>
	<figcaption>
		<p>Let's use an example of a common pattern to explore how Server Actions work. Everyone's favourite feature of the web, the humble cookie bar.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 3.jpg"
		alt="A code snippet of a client-side component that shows/hides a cookie bar"
		loading="lazy"
	/>
	<figcaption>
		<p>Here's a pseudo-code snippet of a pretty normal implementation of a Cookie bar. Let's walk through it. We pull in <code>useState</code> and a third-party client-side cookie library because it's 2023 and we still need a decent interface for reading/setting cookies. We set up some state for whether the cookie has been set or not by reading in the cookie. Now we have two sources of truth&hellip;</p>
		<p>Then we create a method to update our state <strong>and</strong> update the cookie. If the bar has been accepted, we return nothing and if not, we return some markup that renders the bar and calls our method.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 4.jpg"
		alt="A flow diagram of the client-side cookie bar implementation"
		loading="lazy"
	/>
	<figcaption>
		<p>Let's plot this rendering timeline onto a flow-chart.</p>
		<p>The thing about React components is it's easy to forget where they start; rendered on a server. So the request comes into the server and because we're using a client-side cookie library, we don't know whether the cookie has been set or not, so we return nothing. The response gets to the browser and we hit <abbr title="Time to first byte">(TTFB)</abbr>.</p>
		<p>As the page loads, we also get our <abbr title="Largest contentful paint">(LCP)</abbr> before the JS is parsed, hydrated and some time later, is interactive. This marks <abbr title="Time to interactive">(TTI)</abbr>. Only now we can re-check whether the cookie is set, which may or may not show the cookie bar. If it does, we're in danger of triggering a <abbr title="Cumulative layout shift">(CLS)</abbr>. Not good.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 5.jpg"
		alt="Another flow diagram of the client-side cookie bar implementation"
		loading="lazy"
	/>
	<figcaption>
		<p>When the "Accept cookies" button is clicked, everything now happens on the client side. We set our cookie and state, and React re-renders the component, showing/hiding accordingly.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 6.jpg"
		alt="Code snippet of a server action implementation of a cookie bar"
		loading="lazy"
	/>
	<figcaption>
		<p>Here's the equivalent using Server Actions. We pull in the <code>cookies</code> helper from within Next.js, and import a server action that we'll look at in a second. Next, we read directly from the helper, returning <code>null</code> if the cookie is set. Now we return a <code>form</code> with the <code>action</code> attribute set to our imported action. Traditionally, you'd put a string in an <code>action</code> attribute, but under the hood, Next resolves and routes this action so it works without JS. Rather than <code>type="button"</code>, we can use <code>type="submit"</code>. Note, we've not written any client-side code, nor a single <code>event.preventDefault()</code> despite the form.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 7.jpg"
		alt="Code snippet of the cookie bar server action"
		loading="lazy"
	/>
	<figcaption>
		<p>And here's the first Server Action of the day. It's in a file with a <code>'use&nbsp;server'</code> directive. This is crucial, and one of the hallmarks of a Server Action. It tells Next to <strong>never</strong> send this file to the client-side or bundle it into a script so we're safe to work with API secrets and import weightier libraries without penalising our users.</p>
		<p>We import the very same <code>cookies</code> helper as we did in our component and do one thing in the action: set the cookie. Nice and simple.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 8.jpg"
		alt="Rendering flow chart of the server action cookie example"
		loading="lazy"
	/>
	<figcaption>
		<p>The rendering flow chart for this is a dream. The request comes in, with all the lovely headers including any cookies currently set. We either return the markup for the cookie bar, or we don't, but this is all happening on the server. When the response is sent to the client, there's no risk of <abbr title="Cumulative layout shift">(CLS)</abbr>.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 9.jpg"
		alt="Interaction flow chart of the server action cookie example"
		loading="lazy"
	/>
	<figcaption>
		<p>This time, when the button is clicked, a request is sent to the server (via an internal <code>fetch</code> call that Next handles for us). The cookie is checked on the server and the new cookie state is determined. Next then re-renders the component showing/hiding the bar accordingly. From a user's perspective, it's the same outcome, but we've moved the work up to the server. This is a key theme of Server Actions.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 10.jpg"
		alt="Example no. 1.1 - Cookie bar withough Javascript. What happens when JS fails?"
		loading="lazy"
	/>
	<figcaption>
		<p>Now you may be thinking, why does this matter? Well, let's explore the same component with JS disabled for the inevitable moment when JS fails on your site.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 11.jpg"
		alt="Flow chart of the client-side cookie bar with no JS"
		loading="lazy"
	/>
	<figcaption>
		<p>Here's the client-side version again, let's click the button&hellip;</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 12.jpg"
		alt="Everything is broken after the button is clicked."
		loading="lazy"
	/>
	<figcaption>
		<p>&hellip;sad times. It ded.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 13.jpg"
		alt="Flow chart for the Server Action version"
		loading="lazy"
	/>
	<figcaption>
		<p>Now, let's compare it to the Server Action version. You click "accept" and perform a traditional <code>POST</code> request to the server. The cookie is set and the new markup is shown without the cookie bar!</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 14.jpg"
		alt="Benefit no. 1 - No client-side JS required"
		loading="lazy"
	/>
	<figcaption>
		<p>You might not <em>think</em> you care about user's without JS, but <q>All your users are non-JS while they're downloading your JS</q> - <cite>Jake Archibald</cite>.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 15.jpg"
		alt="Benefit no. 2 - Interactive before and during hydration"
		loading="lazy"
	/>
	<figcaption>
		<p>We've all been on pages where the page <em>looks</em> interactive but you're still waiting for the behemoth bundle to parse and hydrate. If your users interact with a Server Action <em>before</em> JS is ready, they'll just follow the non-JS path, and be able to get on with their task quicker than ever.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 16.jpg"
		alt="Gotcha no. 1 - Cookies can only be set in Server Actions & Route handlers"
		loading="lazy"
	/>
	<figcaption>
		<p>Gotcha #1 - as you're interacting with actual request headers, cookies can only be set within Server Actions and route handlers. Once the HTML is sent to the browser, the setting stops.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 17.jpg"
		alt="Gotcha no. 2 - setting cookies in middleware requires cloning headers"
		loading="lazy"
	/>
	<figcaption>
		<p>Gotcha #2 - you can also <em>technically</em> set cookies in Next.js middleware but it requires you to copy headers from the response back to the request or you'll end up in a state where your cookies are a page behind you. This is one of those undocumented features that is only found at the end of a long GitHub issue.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 2 - Slide 18.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Tip #1 - <code>&lt;noscript&gt;</code> and <code>type="hidden"</code> inputs are surprisingly useful with Server Actions.</p>
		<p>Only non-JS users will send the <code>no-js</code> parameter, allowing us handle the two user groups independently.<p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 1.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Onto the next example, a login form. I'll use a simpler "magic link" form to keep things simple.<p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 2.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>This is your common or garden React form. Gosh it's something to behold. Let's work through it. After importing various components, it's time to create some reactive state to hold our email address. Then we create a method to handle the form submission. We send the email to an API and if it's successful, route the user on the client side. We'll ignore error handling for now, but that's another load of complexity to add in.<p>
		<p>Then, <em>on every key press</em>, we set the entered text into state and re-render the whole component to pass the value back to the input you just typed in. This is the two-way data binding we've all come to accept, but it's actually bonkers when you stop and think about it.</p>
		<p>This component covers rendering, API requests and user interactions in the space of 80 lines.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 3.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Let's look at a Server Action equivalent form. The difference is staggering.</p>
		<p>To begin with, it's so focused. It's only concern is providing the markup to render the form. There's no state management per field, no key press events, and no inline functions. Just HTML (well, JSX, but close enough in this case). It uses web standards that have been around for decades: the <code>name</code> attribute, the form <code>action</code>. These things are battle-tested and <em>just work</em> without a tonne of extra complexity.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 4.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>The Server Action doesn't need to be complicated either. Next passes in the <code>FormData</code> instance, so we can easily extract the email using the same <code>name</code> attribute, and pass that to our handler. When that's resolved, we redirect the user to the success page.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 5.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Here's the flow for the Server Action with JS enabled. The form submits, Next sends the data to the Server Action via a POST request with <code>fetch</code>, and on success, it redirects the users through the client-side router.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 6.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Turn off JS and the result is <em>exactly</em> the same. Instead of an AJAX call, a classic POST request happens in the browser, the Server Action handles the login flow, and redirects the user. I would bet money that users would be none the wiser if JS was removed from this page.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 8.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>And for posterity's sake, here's the client-side version with JS turned off. The cookie bar example may have been contrived, but a login form is a primary action for many sites. Through progressive enhancement, Server Actions provide a way for <em>all</em> users to complete primary tasks on a site in all circumstances.</p>
		<p>And moreover, these components are simpler to write and smaller to serve than their client-side counterparts.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 9.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>The reason this all works so neatly, is because these API's follow the <a href="https://frankchimero.com/blog/2015/the-webs-grain/">grain of the web</a>. <code>FormData</code>, for example, is a wonderful web native interface that handles forms incredibly elegantly. It doesn't cost the user anything to import, it's well documented and most importantly, it isn't yet another NPM library negatively effecting your project's maintainability.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 10.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Another weird gotcha - Redirects and <code>try/catch</code> don't work well together in Server Actions&hellip;</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 11.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>If you redirect within the <code>try</code> block, it will throw an error. Use <code>try/catch</code> around asynchronous or volatile calls, then redirect afterwards.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 3 - Slide 12.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Server Actions make it trivial to use API keys/secrets in a responsible manner. Next already requires environment variables you intent to ship to the client-side to be prefixed with <code>NEXT_PUBLIC_</code>, which means any other variable is <em>only</em> usable in a Server Action file.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 1.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Let's carry on from the previous login form example and add some error handling.</p>
		<p>It's important to sanitize our inputs and validate data on the server, not just on the client. With all the data automatically send to the server, this becomes the default pattern using Server Actions.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 2.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Up until now, all our Server Action forms have been server components, and haven't required any client-side state or hooks. That's going to change in this example. Although it's possible to handle error checking with server components, we're going to use the new <code>useFormState</code> hook imported not from Next, but from <code>react-dom</code>. You need to mark the file with a <code>'use&nbsp;client'</code> directive.</p>
		<p>This hook takes in the Server Action import, and some default state in the shape of an object. It returns an array with a the reactive state, and a new embellished Server Action. These can then be applied to the form and used to render error messages.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 3.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Looking at the updated Server Action, you'll see we now return a JSON object if there's an error generated in the <code>try/catch</code> block. This object will be returned to the client and the form updated to show the error message.</p>
		<p>The <code>try/catch</code> pattern works really nicely here, allowing us to liberally throw errors in validation libraries, or within the login flow, and handle them in a consistent way.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 4.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Here's the flow chart of what's going on, showing the early JSON response if the error is present, and the redirect on success&hellip;</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 5.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>&hellip;and without JS, it works very similarly&hellip;</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 6.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>&hellip;but there is a gotcha here. You'll probably remember this classic error message. It appears if you try and refresh a page that has been rendered directly from a POST request. Depending on the task, it could be pretty bad news if a user can resubmit the same form multiple times.</p>
		<p>Non-js users can get into this state when we return an error response message. That's not a big deal, but could be if we used <code>useFormState</code> to handle a success state, rather than redirecting the user onto another page.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 7.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>We can keep things idempotent with the POST → Redirect → GET pattern. This approach ensures that redirects are <a href="https://www.w3.org/TR/design-principles/#safe-to-browse">safe</a> and without side-effects.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 8.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Time for another gotcha. The Edge runtime might sound like a U2 effects pedal, but it's the name given to the flavour of limited JS used on CDN servers. At build-time, Next breaks down an application into a bunch of smaller functions that can be distributed to 'Edge' servers and run from there, rather than on a single, central server. This is all very clever and helps with performance, but it's also required to opt-into for Server Actions, specifically if you want to support non-JS requests.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 9.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>These two, barely documented exports need to be set within the page importing the server action. You won't notice an issue when running the application in development mode, but without <code>export const runtime = 'edge';</code>, non-JS POST requests will just hang indefinently.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 10.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>A popular JS validation library is Zod. It's very good. It's also recommended on the Next.js Server Actions documentation. It has a <code>FormData</code> plugin designed to take in a POST request and validate accordingly. Unfortunately, that plugin doesn't work with the Edge runtime and thus can't be used with Server Actions if you want to support non-JS users. I'm not sure if anyone at Vercel has noticed.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 11.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>We use DataDog for logging, monitoring and alerting. But again, there's a gotchat here. I was finding our nice, tidy logs were being desecrated by nasty multi-line logs, but only on some requests. You guessed it, it's our friend the Edge runtime again.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 4 - Slide 12.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Within our Pino logger, I had to take charge of the logging, but only for requests currently using the Edge runtime in production.</p>
		<p>This has formatted logs to a single line, but some events continue to appear as <code>info</code>, despite being classified as <code>error</code>.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 5 - Slide 1.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>The final update to the login form example involves adding a loading state.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 5 - Slide 2.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p><code>useFormStatus</code> from <code>react-dom</code> is the hook needed for this feature. It returns an object with a <code>pending</code> property, which updates when the form is being submitted. We can use this to show a loading/disabled state on the submit button.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 5 - Slide 3.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>Big gotcha for this - <code>useFormStatus</code> must be used in a child component to the form. It <strong>cannot</strong> be used directly in the parent component.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 6 - Slide 1.jpg"
		alt=""
		loading="lazy"
	/>
	<figcaption>
		<p>To finish, I'll run through a few quickfire tips.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 6 - Slide 2.jpg"
		alt="useOptimistic can update the UI before the server action completes - perfect for event driven architectures"
		loading="lazy"
	/>
	<figcaption>
		<p><code>useOptimistic</code> is a hook provided to update the UI before the Server Action has completed. The classic example for this is an instant messaging application. <a href="https://lawsofux.com/jakobs-law/">Jakob's law</a> suggests that you expect to be able to hit enter on a message and it will appear in the message list instantly, rather than waiting for the server to respond positively that the message has been sent. This hook provides some plumbing to make this pattern simpler to implement.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 6 - Slide 3.jpg"
		alt="Server Actions can GET data on page load in a server component"
		loading="lazy"
	/>
	<figcaption>
		<p>Server Actions can be used to fetch data on page/layout load. This is a instance where an action won't receive a FormData object, and can be supplied with whatever parameters you'd like. You're also likely to return an object, rather than a redirect in these instances.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 6 - Slide 4.jpg"
		alt="Server actions only every POST data from forms"
		loading="lazy"
	/>
	<figcaption>
		<p>However, you cannot run a Server Action from a form as a GET request, only a POST. In fact, Next will just steamroll your <code>method</code> parameter and force a POST on there.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 6 - Slide 5.jpg"
		alt="revalidatePath - bust the cache on a route before redirecting"
		loading="lazy"
	/>
	<figcaption>
		<p><abbr title="Create. Read. Update. Delete.">CRUD</abbr> updates are a pretty common usecase for Server Actions. So when you create/update/delete your todo/comment/post etc, you're probably going to want to refresh the list of todos/comments/posts to reflect the change.</p>
		<p><code>revalidatePath</code> accepts a relative URL string where it will flush the cache for any data persisted on that route. When you next visit the route, it will refetch the latest copy of the data, rather than respond with an earlier cached copy.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 6 - Slide 6.jpg"
		alt="revalidateTag - mark up your fetch calls with tags and call this in a server action to bust the cache"
		loading="lazy"
	/>
	<figcaption>
		<p>If you're using the monkey-patched <code>fetch</code> implementation within Next, you're going to want to swat up on <a href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating">caching</a> within the framework. Next now caches <em>everything</em>. If you're dealing with user-specific data, you're going to want to tag up your <code>fetch</code> calls to avoid the risk of cross-pollinating another user's data. I like to include a user ID within the tag to ensure they're unique per user.</p>
		<p><code>revalidateTag</code> accepts one of those tags and busts the cache for it.</p>
	</figcaption>
</figure>
<figure>
	<img
		width="1152 "
		height="648"
		src="/images/blog/next-server-actions/Section 7 - Slide 1.jpg"
		alt="Thanks for listening"
		loading="lazy"
	/>
	<figcaption>
		<p>Thanks for <del>listening</del> reading!</p>
	</figcaption>
</figure>
]]>
      </description>
    </item>
    
    <item>
      <title>ApolloClient with SSR</title>
      <link>https://www.trysmudford.com/blog/apolloclient-with-ssr/</link>
      <pubDate>Mon, 19 Nov 2018 00:00:00 +0000</pubDate>
      
      <guid>https://www.trysmudford.com/blog/apolloclient-with-ssr/</guid>
      <description><![CDATA[
<p>I recently came across an curious issue with <code>ApolloClient</code> on a server-side render. The GraphQL results wouldn&rsquo;t update until I restarted the server.</p>
<p>In a client-side app, a <code>new ApolloClient</code> gets created for each page load. But in a <code>node.js</code> service, it runs once on application launch and sits in memory till the whole application has been killed - that could be days or weeks.</p>
<p>Not only that, as the server-side <code>ApolloClient</code> sits in memory, it&rsquo;s shared between every user connection, and is therefore ripe for leaking data between connections. Not what we want.</p>
<p>To overcome this problem, we instantiate a <code>new ApolloClient</code> for each connection. We can wrap this up in a nice reusable method:</p>
<div class="highlight"><pre class="chroma"><code class="language-ts" data-lang="ts"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloClient</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;apollo-client&#39;</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">createHttpLink</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;apollo-link-http&#39;</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">InMemoryCache</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;apollo-cache-inmemory&#39;</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">withClientState</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;apollo-link-state&#39;</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloLink</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;apollo-link&#39;</span><span class="p">;</span>

<span class="kr">const</span> <span class="nx">CreateClient</span> <span class="o">=</span> <span class="p">(</span><span class="nx">defaults</span> <span class="o">=</span> <span class="p">{},</span> <span class="nx">links</span>: <span class="kt">any</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[])</span><span class="o">:</span> <span class="nx">ApolloClient</span><span class="o">&lt;</span><span class="p">{}</span><span class="o">&gt;</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kr">const</span> <span class="nx">cache</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">InMemoryCache</span><span class="p">();</span>

  <span class="kr">const</span> <span class="nx">stateLink</span> <span class="o">=</span> <span class="nx">withClientState</span><span class="p">({</span>
    <span class="nx">cache</span><span class="p">,</span>
    <span class="nx">resolvers</span><span class="o">:</span> <span class="p">{},</span>
    <span class="nx">defaults</span>
  <span class="p">});</span>

  <span class="k">return</span> <span class="k">new</span> <span class="nx">ApolloClient</span><span class="p">({</span>
    <span class="nx">connectToDevTools</span>: <span class="kt">false</span><span class="p">,</span>
    <span class="nx">ssrMode</span>: <span class="kt">true</span><span class="p">,</span>
    <span class="nx">link</span>: <span class="kt">ApolloLink.from</span><span class="p">([</span>
      <span class="nx">stateLink</span><span class="p">,</span>
      <span class="p">...</span><span class="nx">links</span><span class="p">,</span>
      <span class="nx">createHttpLink</span><span class="p">({</span>
        <span class="nx">uri</span>: <span class="kt">process.env.GRAPHQL_URL</span>
      <span class="p">})</span>
    <span class="p">]),</span>
    <span class="nx">cache</span>
  <span class="p">});</span>
<span class="p">};</span>

<span class="kr">export</span> <span class="p">{</span> <span class="nx">CreateClient</span> <span class="p">};</span>
</code></pre></div><p>We can then import the file on launch, and crucially, run the <code>CreateClient</code> function for each request. Not only that, we can pass in <code>defaultState</code> and prime the <code>apollo-link-state</code> cache with any user defaults. Furthermore, we can add additional link helpers like <code>onError</code>.</p>
<div class="highlight"><pre class="chroma"><code class="language-jsx" data-lang="jsx"><span class="nx">server</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;/*&#39;</span><span class="p">,</span> <span class="kr">async</span> <span class="p">(</span><span class="nx">req</span><span class="o">:</span> <span class="nx">express</span><span class="p">.</span><span class="nx">Request</span><span class="p">,</span> <span class="nx">res</span><span class="o">:</span> <span class="nx">express</span><span class="p">.</span><span class="nx">Response</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
  <span class="kr">const</span> <span class="nx">defaultState</span> <span class="o">=</span> <span class="p">{};</span>
  <span class="kr">const</span> <span class="nx">errorLink</span> <span class="o">=</span> <span class="nx">onError</span><span class="p">((</span><span class="nx">error</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{});</span>

  <span class="kr">const</span> <span class="nx">client</span><span class="o">:</span> <span class="nx">ApolloClient</span><span class="o">&lt;</span><span class="p">{}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="nx">CreateClient</span><span class="p">(</span><span class="nx">defaultState</span><span class="p">,</span> <span class="p">[</span><span class="nx">errorLink</span><span class="p">]);</span>

  <span class="kr">const</span> <span class="nx">Application</span> <span class="o">=</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">(</span>
      <span class="p">&lt;</span><span class="nt">ApolloProvider</span> <span class="na">client</span><span class="o">=</span><span class="p">{</span><span class="nx">client</span><span class="p">}&gt;</span>
        <span class="p">&lt;</span><span class="nt">App</span> <span class="p">/&gt;</span>
      <span class="p">&lt;/</span><span class="nt">ApolloProvider</span><span class="p">&gt;</span>
    <span class="p">)</span>
  <span class="p">}</span>
</code></pre></div><h2 id="reusing-createclient">Reusing CreateClient</h2>
<p>We could&rsquo;ve run all that <code>CreateClient</code> code within the <code>server.get</code> method, but by moving it outside, we can reuse it in our tests. This time, there&rsquo;s no <code>defaultState</code> or additional links, so we can call <code>createClient</code> directly.</p>
<div class="highlight"><pre class="chroma"><code class="language-jsx" data-lang="jsx"><span class="kr">import</span> <span class="o">*</span> <span class="nx">as</span> <span class="nx">React</span> <span class="nx">from</span> <span class="s1">&#39;react&#39;</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">ApolloClient</span> <span class="nx">from</span> <span class="s1">&#39;apollo-client&#39;</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloProvider</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;react-apollo&#39;</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">mount</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;enzyme&#39;</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">CreateClient</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@/gql/CreateClient&#39;</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">User</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@/pages/User&#39;</span><span class="p">;</span>

<span class="nx">describe</span><span class="p">(</span><span class="s1">&#39;&lt;User /&gt; page&#39;</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="p">{</span>
  <span class="kr">const</span> <span class="nx">client</span><span class="o">:</span> <span class="nx">ApolloClient</span><span class="o">&lt;</span><span class="p">{}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="nx">CreateClient</span><span class="p">();</span>
  <span class="nx">it</span><span class="p">(</span><span class="s1">&#39;renders a user profile&#39;</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="p">{</span>
    <span class="nx">mount</span><span class="p">(</span>
      <span class="p">&lt;</span><span class="nt">ApolloProvider</span> <span class="na">client</span><span class="o">=</span><span class="p">{</span><span class="nx">client</span><span class="p">}&gt;</span>
        <span class="p">&lt;</span><span class="nt">User</span> <span class="na">match</span><span class="o">=</span><span class="p">{{</span> <span class="nx">params</span><span class="o">:</span> <span class="p">{</span> <span class="nx">username</span><span class="o">:</span> <span class="s1">&#39;trys&#39;</span> <span class="p">}</span> <span class="p">}}</span> <span class="p">/&gt;</span>
      <span class="p">&lt;/</span><span class="nt">ApolloProvider</span><span class="p">&gt;</span>
    <span class="p">);</span>
  <span class="p">});</span>
<span class="p">});</span>
</code></pre></div>]]>
      </description>
    </item>
    
    <item>
      <title>Named exports withApollo in Typescript React</title>
      <link>https://www.trysmudford.com/blog/named-exports-withapollo-typescript-react/</link>
      <pubDate>Tue, 06 Nov 2018 00:00:00 +0000</pubDate>
      
      <guid>https://www.trysmudford.com/blog/named-exports-withapollo-typescript-react/</guid>
      <description><![CDATA[
<p>I came across a small hurdle when working with GraphQL fragments. To get access to the Apollo client, it needed to be wrapped in the <code>withApollo</code> higher-order component, a task which is usually straightforward. However, things are a little more tricky when the component uses named exports.</p>
<p>Here&rsquo;s a &lsquo;standard&rsquo; component as a starting point:</p>
<div class="highlight"><pre class="chroma"><code class="language-js" data-lang="js"><span class="kr">import</span> <span class="o">*</span> <span class="nx">as</span> <span class="nx">React</span> <span class="nx">from</span> <span class="s1">&#39;react&#39;</span>

<span class="kr">class</span> <span class="nx">Sidebar</span> <span class="kr">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span> <span class="p">{</span>
  <span class="kr">public</span> <span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
    <span class="c1">// ...
</span><span class="c1"></span>  <span class="p">}</span>
<span class="p">}</span>

<span class="kr">export</span> <span class="p">{</span> <span class="nx">Sidebar</span> <span class="p">}</span>
</code></pre></div><p>On the surface, that final line looks like a ordinary object with property/value shorthand, but sadly that&rsquo;s not the case. Assignment within that &lsquo;object&rsquo; is not allowed, it <strong>only accepts a comma separated list</strong>. This prevents <code>withApollo</code> being assigned in a &lsquo;normal&rsquo; object-y way:</p>
<div class="highlight"><pre class="chroma"><code class="language-js" data-lang="js"><span class="kr">export</span> <span class="p">{</span> <span class="nx">Sidebar</span><span class="o">:</span> <span class="nx">withApollo</span><span class="p">(</span><span class="nx">Sidebar</span><span class="p">)</span> <span class="p">}</span>
</code></pre></div><h2 id="the-solution">The solution</h2>
<p>Although not very elegant, the best solution I found was to rename the original class declaration and export the correctly named wrapped variable:</p>
<div class="highlight"><pre class="chroma"><code class="language-js" data-lang="js"><span class="kr">import</span> <span class="p">{</span> <span class="nx">withApollo</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;react-apollo&#39;</span><span class="p">;</span>

<span class="kr">class</span> <span class="nx">SidebarComponent</span> <span class="kr">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span> <span class="p">{</span>
  <span class="kr">public</span> <span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
    <span class="c1">// ...
</span><span class="c1"></span>  <span class="p">}</span>
<span class="p">}</span>

<span class="kr">export</span> <span class="kr">const</span> <span class="nx">Sidebar</span> <span class="o">=</span> <span class="nx">withApollo</span><span class="p">(</span><span class="nx">SidebarComponent</span><span class="p">);</span>
</code></pre></div><h2 id="now-with-added-typescript">Now with added Typescript</h2>
<p>The above code works well in JS-land, but Typescript tends to get a bit grumpy. The component needs to be aware of props being passed in from the <code>withApollo</code> <abbr title="Higher-order component">HOC</abbr>. The solution is to add a new type to the component:</p>
<div class="highlight"><pre class="chroma"><code class="language-ts" data-lang="ts"><span class="kr">import</span> <span class="o">*</span> <span class="kr">as</span> <span class="nx">React</span> <span class="kr">from</span> <span class="s1">&#39;react&#39;</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">withApollo</span><span class="p">,</span> <span class="nx">WithApolloClient</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;react-apollo&#39;</span><span class="p">;</span>

<span class="kr">class</span> <span class="nx">SidebarComponent</span> <span class="kr">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span><span class="p">&lt;</span><span class="nt">WithApolloClient</span><span class="err">&lt;</span><span class="p">{}&gt;</span><span class="o">&gt;</span> <span class="p">{</span>
  <span class="kr">public</span> <span class="nx">render() {</span>
    <span class="c1">// ...
</span><span class="c1"></span>  <span class="p">}</span>
<span class="p">}</span>

<span class="kr">export</span> <span class="kr">const</span> <span class="nx">Sidebar</span> <span class="o">=</span> <span class="nx">withApollo</span><span class="p">(</span><span class="nx">SidebarComponent</span><span class="p">);</span>
</code></pre></div><p>If you already have some custom props defined on the component, they can be nested within the <code>WithApolloClient</code> annotation:</p>
<div class="highlight"><pre class="chroma"><code class="language-ts" data-lang="ts"><span class="kr">interface</span> <span class="nx">Props</span> <span class="p">{</span>
  <span class="nx">id</span>: <span class="kt">number</span><span class="p">;</span>
<span class="p">}</span>

<span class="kr">class</span> <span class="nx">SidebarComponent</span> <span class="kr">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span><span class="p">&lt;</span><span class="nt">WithApolloClient</span><span class="err">&lt;</span><span class="na">Props</span><span class="p">&gt;</span><span class="o">&gt;</span>
</code></pre></div>]]>
      </description>
    </item>
    
  </channel>
</rss>