<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Moray Macdonald</title>
    <description>The latest articles on Forem by Moray Macdonald (@moraym).</description>
    <link>https://forem.com/moraym</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F701814%2F2c613736-8535-479d-b9ef-7f8eeac891be.png</url>
      <title>Forem: Moray Macdonald</title>
      <link>https://forem.com/moraym</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/moraym"/>
    <language>en</language>
    <item>
      <title>Using AWS IAM roles with Node SDKv3</title>
      <dc:creator>Moray Macdonald</dc:creator>
      <pubDate>Tue, 08 Oct 2024 10:55:54 +0000</pubDate>
      <link>https://forem.com/moraym/using-aws-iam-roles-with-node-sdkv3-2246</link>
      <guid>https://forem.com/moraym/using-aws-iam-roles-with-node-sdkv3-2246</guid>
      <description>&lt;p&gt;Recently I was upgrading our Node backend and decided to upgrade our S3 helpers from AWS SDKv2 to SDKv3. Apart from splitting the SDK into individual dependencies for each component (very nice), it also makes some pretty major changes around how requests are made.&lt;/p&gt;

&lt;p&gt;Once I got my head around creating command objects and sending them to the client instead of just called the appropriate method, the migration was fairly smooth and worked well with the test credentials on my dev machine. Unfortunately, as soon as I started to roll out the changes onto our staging environment, my logs started filling up with familiar "Could not load credentials from any providers" errors. Normally this is a sign to any AWS veterans that you've forgotten to give your EC2 instance the right IAM role, but in this case all the instances had the right role, and the role still had the correct permissions.&lt;/p&gt;

&lt;p&gt;After a bit of digging, I came across &lt;a href="https://repost.aws/questions/QUXMX9z9zCSb21qsnedFZQpg/having-trouble-converting-aws-node-sdk-v2-lambda-to-v3" rel="noopener noreferrer"&gt;this forum post&lt;/a&gt; which contained the answer. In SDKv3, the credential provider that comes with the individual service packages has been made much stricter and can only read credentials from certain places. This means that the new &lt;code&gt;S3Client&lt;/code&gt; &lt;em&gt;can't&lt;/em&gt; read credentials inserted into your EC2 instance from its IAM role via the Instance Metadata Service (IMDS).&lt;/p&gt;

&lt;p&gt;If you are getting credentials based on your instance's IAM role (and if not, why not?) you need to specify the credential provider explicitly from the &lt;a href="https://www.npmjs.com/package/@aws-sdk/credential-provider-node" rel="noopener noreferrer"&gt;credential-provider-node&lt;/a&gt; package. So for example, if you need to access S3 resources, you need to do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;S3Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@aws-sdk/client-s3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defaultProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@aws-sdk/credential-provider-node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eu-west-2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;defaultProvider&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other clients for other services also have the &lt;code&gt;credentials&lt;/code&gt; option. Now you should be able to access your services as you expect!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>node</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Which React render callback pattern do you prefer?</title>
      <dc:creator>Moray Macdonald</dc:creator>
      <pubDate>Mon, 23 Sep 2024 16:47:08 +0000</pubDate>
      <link>https://forem.com/moraym/which-react-render-callback-pattern-do-you-prefer-3p5a</link>
      <guid>https://forem.com/moraym/which-react-render-callback-pattern-do-you-prefer-3p5a</guid>
      <description>&lt;p&gt;I found myself with an hour to myself on Friday afternoon so thought I'd relax with a good old refactoring session to tidy up some deeper parts of our React app. Whilst digging, I found that we use a couple of different abstraction patterns when one component needs to control the rendering of another. In both cases, the parent component runs a callback function to control the rendering of the child component (hence the name - callback pattern) but I can't decide which form I prefer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;In my case, the parent component was part of our authorization logic which is way to complex to reproduce here, so I've simplified things! The idea is that the (reusable) parent does some processing, generates some props, and passes those props down to the child component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Render Prop pattern
&lt;/h3&gt;

&lt;p&gt;In this case, the parent component uses a prop called &lt;code&gt;render&lt;/code&gt; which sets the logic to render the child component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RenderPropsExample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RenderPropParent&lt;/span&gt; &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SubComponent&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Function as a Child (FaaC)
&lt;/h3&gt;

&lt;p&gt;In this case, the built-in &lt;code&gt;children&lt;/code&gt; property of the parent element sets the logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FunctionAsChildExample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChildComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SubComponent&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ChildComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Which is better?
&lt;/h2&gt;

&lt;p&gt;As the end result is the same for both cases, is that even the right question to ask?&lt;/p&gt;

&lt;p&gt;Personally, I like the way the FaaC pattern uses the built-in &lt;code&gt;children&lt;/code&gt; feature of React, but I don't like the fact that I have to redefine &lt;code&gt;children&lt;/code&gt; to be a function that returns a &lt;code&gt;ReactNode&lt;/code&gt;, rather than just a &lt;code&gt;ReactNode&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the other hand, the Render Prop pattern doesn't have that issue - &lt;code&gt;render&lt;/code&gt; is a custom prop so I'm free to define it however I like. But using a prop to define my component hierarchy instead of child components feels like I'm again breaking a pretty fundamental pattern in React!&lt;/p&gt;

&lt;p&gt;What are your thoughts on this? Have I missed a way that one is superior to the other? Or is this a pointless discussion as the end result is the same? Let me know!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>What's your favourite TypeScript style guide (and why)?</title>
      <dc:creator>Moray Macdonald</dc:creator>
      <pubDate>Wed, 06 Sep 2023 16:08:54 +0000</pubDate>
      <link>https://forem.com/moraym/whats-your-favourite-typescript-style-guide-and-why-3djo</link>
      <guid>https://forem.com/moraym/whats-your-favourite-typescript-style-guide-and-why-3djo</guid>
      <description>&lt;p&gt;I had an interesting chat with another dev about the pros and cons of different style guides yesterday and was interested to see what everyone else uses.&lt;/p&gt;

&lt;p&gt;Personally I like how prescriptive the AirBnB style guide is (with the TS addon, I know it's not officially supported) which really helps with readability across large projects, but I know not everyone likes.&lt;/p&gt;

&lt;p&gt;So, what's your favourite? React for the poll, and comment why!&lt;/p&gt;

&lt;p&gt;(in alphabetical order 😉)&lt;/p&gt;

&lt;p&gt;💖 I like AirBnB&lt;br&gt;
🦄 I like Google&lt;br&gt;
🤯 I like Standard&lt;br&gt;
🙌 I like XO&lt;br&gt;
🔥 I use some other style guide (write in)/I have my own rules&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Making better images with HTML5 and React</title>
      <dc:creator>Moray Macdonald</dc:creator>
      <pubDate>Sat, 11 Mar 2023 22:06:04 +0000</pubDate>
      <link>https://forem.com/moraym/making-better-images-with-html5-and-react-12dp</link>
      <guid>https://forem.com/moraym/making-better-images-with-html5-and-react-12dp</guid>
      <description>&lt;p&gt;I love HTML5. I love its semantic elements. I love its accessibility features. Mostly, I love the fact that its designers clearly looked at all the problems that web developers were having with HTML4, and all the libraries and hacks we were using to get around them and decided "Right. We'll fix that." And for the most part they did!&lt;/p&gt;

&lt;p&gt;One of the things that every web developer will encounter is how to show images to the user. Unfortunately, displaying images is a lot more complex than &lt;code&gt;&amp;lt;img src="cat.jpg"&amp;gt;&lt;/code&gt;, when you start considering all the different people who'll be using your site - us devs have nice big screens  and fast internet connections, but a user on a narrow mobile screen with a slow connection is not going to want to wait to load your gorgeous hi-res header image. And that's before we get to my gran, who still has a beige tower PC and a web browser that's barely heard of PNG, let alone fancy things like WEBP and AVIF!&lt;/p&gt;

&lt;p&gt;Fortunately, HTML5 is here to the rescue with its very handy &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element! Here's what it looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/static/cat-1024x768.webp"&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;
    &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 800px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/static/cat-1024x768.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/jpeg"&lt;/span&gt;
    &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 800px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/static/cat-800x600.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/jpeg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/static/cat-1024x768.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"You should really title your images!"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"You should alt text them too. Screen readers and crawlers will thank you!"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks far more complex than &lt;code&gt;&amp;lt;img src="cat.jpg"&amp;gt;&lt;/code&gt;, but what the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element does is actually very clever and very simple. It looks at all the possible things it can display (the &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt; elements), and then picks the most appropriate one to load and display to the user using the supplied &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element.&lt;/p&gt;

&lt;p&gt;So for the example above, the browser will go through the following logic:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If I support WEBP images, and is my width greater than 800px? If so, pick the first &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If I don't support WEBP but my width is greater than 800px, I'll pick the second &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If I'm less than 800px wide I'll pick the last &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If I'm really old and don't support HTML5, I'll just render the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag and use whatever is in its &lt;code&gt;src&lt;/code&gt; attribute.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This gives us a HUGE amount of flexibility to show the most appropriate images for whatever browser our users are using, so after you've finished reading this article, have a look at the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture"&gt;documentation&lt;/a&gt; - there's some great stuff you can do with pixel density selectors and more!&lt;/p&gt;

&lt;p&gt;The most important element in the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; is still the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element - in fact, it's required otherwise old browsers can't render anything! That &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; controls how the final image is displayed - so that's what you should stick your CSS classes, titles and alt text to.&lt;/p&gt;

&lt;p&gt;So that's how the HTML works, but how can we make that work in React? Very simply, as it turns out! In most of my web projects I create a component like the one below. Please note that it doesn't expose &lt;em&gt;all&lt;/em&gt; the features of &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;, only the ones I most commonly use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Picture&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// I don't like typing out the &amp;lt;source&amp;gt; elements in full&lt;/span&gt;
  &lt;span class="c1"&gt;// so I just pass in the key properties&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sourceElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sources&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;source&lt;/span&gt; &lt;span class="na"&gt;srcset&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mime&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;media&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`(min-width: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px)`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;source&lt;/span&gt; &lt;span class="na"&gt;srcset&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;srcset&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mime&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;sourceElements&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to produce the example I showed at the start I use it like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;imageJpg&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../img/cat-1024x768.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;imageSmallJpg&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../img/cat-800x600.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;imageWebp&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../img/cat-1024x768.webp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;HowToUseIt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Picture&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"You should really title your images!"&lt;/span&gt;
      &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"You should alt text them too. Don't be lazy!"&lt;/span&gt;
      &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;imageJpg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageWebp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image/webp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageJpg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image/jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageSmallJpg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image/jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Easy to read and easy to use! Drop it into your next project and hopefully watch your Lighthouse scores increase...&lt;/p&gt;

&lt;p&gt;Thanks for reading! Let me know if you found it useful, and if you've got any improvements to make to my little component 😄&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>html</category>
    </item>
  </channel>
</rss>
