<?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>DEV Community: Tim Bright</title>
    <description>The latest articles on DEV Community by Tim Bright (@40percentironman).</description>
    <link>https://dev.to/40percentironman</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%2F502756%2F90e50a74-3c0b-4f05-8a5c-5cbe41da0a5e.png</url>
      <title>DEV Community: Tim Bright</title>
      <link>https://dev.to/40percentironman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/40percentironman"/>
    <language>en</language>
    <item>
      <title>Frontend Code from a Backend Perspective</title>
      <dc:creator>Tim Bright</dc:creator>
      <pubDate>Tue, 26 Nov 2024 03:03:52 +0000</pubDate>
      <link>https://dev.to/40percentironman/frontend-code-from-a-backend-perspective-47i7</link>
      <guid>https://dev.to/40percentironman/frontend-code-from-a-backend-perspective-47i7</guid>
      <description>&lt;p&gt;I don't call myself a frontend developer.&lt;/p&gt;

&lt;p&gt;To be clear, I know how to do frontend work. I'm trying to keep myself up-to-date with all the newest ways to try to more easily put content on the browser in a performant way. I build web applications, so you have to know how to build a user-facing client to call your backend.&lt;/p&gt;

&lt;p&gt;I would call myself a backend developer.&lt;/p&gt;

&lt;p&gt;But I definitely wouldn't call myself a frontend developer.&lt;/p&gt;

&lt;p&gt;People say the frontend is the "easy" work. I don't. For me, it's a special kind of hell where you have every tool available but none of the right ones. It always seemed to me that it was inevitable that frontend code always ends up in spaghetti and you have to scrap and redo it periodically.&lt;/p&gt;

&lt;p&gt;Recently, I found a paradigm that resonates with me and I thought I'd share my thinking. It came to me from a more backend-focused perspective, but the more I think about it, I see it's just good programming practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Architecture: The Lost Years"
&lt;/h2&gt;

&lt;p&gt;One of the talks that influenced me the most was one Robert "Uncle Bob" Martin has that's titled &lt;em&gt;"Architecture: The Lost Years"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/WpkDN78P884"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In it, he laments how software development evolved over the last few decades:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I call this talk 'The Lost Years' [...] because from 1993 until now we have forgotten this thing we were on the verge of learning...and do you know what drove it out of our heads? The Web. The Web was so all-consuming [...] and it drove all those ideas out of our brains for [years] and they're just now starting to come back..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, I will say Uncle Bob has some hot takes. There are a lot of people that disagree with him on his version of what "clean code" is (and I'm one of them). I try not to blindly parrot his or anyone's takes, or follow them without a deeper understanding of what they're trying to say. I can't speak to this "Middle Ages of Software Architecture" that he seems to be referring to. Back in 1991 when the Web was new, I think I was just starting to write my first "Hello world" applications in C++. Compared to him and lot of others, I'm a relative n00b.&lt;/p&gt;

&lt;p&gt;However, I have noticed that there seems to be a rift between what people say we &lt;em&gt;should&lt;/em&gt; do, and what we &lt;em&gt;actually&lt;/em&gt; do in practice. For example: &lt;strong&gt;why do most of the web app test suites I've ever seen require the web server to be running in order to run the tests?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unless you're testing for the actual user responses being received (which can be tested independent of the business logic), &lt;em&gt;there's absolutely no reason for the web server to be running.&lt;/em&gt; Whenever I've seen it, it's an artifact of treating the web server as the central abstraction of the application. The application then becomes a web server spidered with business logic. In order to test the code, you need to run the web server for the tests and do mock HTTP calls to it. This makes your testing unnecessarily slow because you have the web server in the middle of it.&lt;/p&gt;

&lt;p&gt;I've seen the same thing with frontend code. In a lot of cases, you're not able to test the business logic independent of the UI. &lt;em&gt;Why should I have to render the React code to test fetching data from the backend?&lt;/em&gt;  React is a UI framework; it should never be the central abstraction for my frontend code. However, that's what it seems most frontend clients are: "React apps" instead of applications using React. It also seems that most tutorials (and even some tools!) direct you to "Reactify" all your code, further feeding into this pattern of making React the center of your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmj9zjc2aeoxiqnrfl3gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmj9zjc2aeoxiqnrfl3gy.png" alt="Thanks to Uncle Bob for this image: https://www.youtube.com/watch?v=o_TH-Y78tt4&amp;amp;t=2581s" width="800" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Ports and Adapters" Pattern
&lt;/h2&gt;

&lt;p&gt;So how can we avoid this?&lt;/p&gt;

&lt;p&gt;Uncle Bob's architectural recommendation in that talk is remarkably similar to the "ports and adapters" pattern for hexagonal architecture. What Uncle Bob calls the &lt;em&gt;interactor&lt;/em&gt; object is a part of the application. It implements a specific interface that defines the functions of how the application object should be interacted with. To use the "ports and adapters" language, the interface is a port, and the interactor is an adapter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Application {
  doAppFunction(): void;
}

class Interactor extends Application {
  constructor(...) { }

  public doAppFunction() {
    ...execute some application code
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adapter can be plugged into another bit of code that uses the port, perhaps as an argument to a function or it can be dependency injected at creation time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UI {
   constructor(app: Application) { this.app = app; }

   someUIFunction() {
      ...

      this.app.doAppFunction();

      ... do other UI code
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, the UI can do application-specific functions via the &lt;code&gt;Application&lt;/code&gt; interface but the UI code does not contain any of that code. This allows you to test the &lt;code&gt;Interactor&lt;/code&gt; object independently from the UI, meaning you don't have to run the UI and also you don't have to run the app to do UI unit tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Working with React
&lt;/h3&gt;

&lt;p&gt;So how would this work with React?&lt;/p&gt;

&lt;p&gt;One way to do this is to make a React &lt;code&gt;Context&lt;/code&gt; that holds an &lt;code&gt;Application&lt;/code&gt; object and then just fetch the object with &lt;code&gt;useContext&lt;/code&gt; whenever you need to interact with something outside of React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const AppContext = createContext&amp;lt;Application&amp;gt;(undefined);

export const useApplication = () =&amp;gt; {
  const context = useContext(AppContext);
  if (!context) {
    throw new Error("useApplication must be used within a ApplicationProvider");
  }
  return context;
};

export const ApplicationProvider = (props) =&amp;gt; {
  const { children, value } = props;
  return &amp;lt;AppContext.Provider value={value}&amp;gt;{children}&amp;lt;/AppContext.Provider&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can create the &lt;code&gt;Interactor&lt;/code&gt; object just before you render your React application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const application = new Interactor();

export const renderApp = () =&amp;gt; {
  const root = document.getElementById("root");
  ReactDOM.createRoot(root).render(
    &amp;lt;React.StrictMode&amp;gt;
      &amp;lt;ApplicationProvider value={application}&amp;gt;
        &amp;lt;MyReactApp /&amp;gt;
      &amp;lt;/ApplicationProvider&amp;gt;
    &amp;lt;/React.StrictMode&amp;gt;,
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can use the hook in the children to get access to the &lt;code&gt;Application&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const MyReactApp = () =&amp;gt; {
  const app = useApplication();
  app.doAppFunction();

  return &amp;lt;&amp;gt; ... &amp;lt;/&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern allows you to separate your UI from what essentially are your models and controllers. You can now work with app state and not have to bind it with React's UI state, which gives you a lot of control. However, you can still use tools like &lt;code&gt;@tanstack/query&lt;/code&gt; to control overzealous calls to your application object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Mileage May Vary
&lt;/h2&gt;

&lt;p&gt;I know I'm going against the grain on this one.&lt;/p&gt;

&lt;p&gt;I'm probably going to  get a lot of comments like, &lt;em&gt;"You shouldn't do that because _&lt;/em&gt;__ and _____&lt;em&gt;, you n00b!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And that's okay.&lt;/p&gt;

&lt;p&gt;I don't claim to be a frontend developer.&lt;/p&gt;

&lt;p&gt;But I will say my frontend code became a lot more simple once I started using this pattern. This same thing actually happened when I started doing this with my backend code as well. I would inject my app dependencies into my app object, and then I would inject my app object as a dependency to my REST/GraphQL/gRPC code. It abstracted a lot of the unnecessary details away and kept my concerns separate.&lt;/p&gt;

&lt;p&gt;Try it out. You might like it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Distribute your Go CLI tools with GoReleaser and Homebrew</title>
      <dc:creator>Tim Bright</dc:creator>
      <pubDate>Fri, 01 Sep 2023 22:01:08 +0000</pubDate>
      <link>https://dev.to/40percentironman/distribute-your-go-cli-tools-with-goreleaser-and-homebrew-4jd8</link>
      <guid>https://dev.to/40percentironman/distribute-your-go-cli-tools-with-goreleaser-and-homebrew-4jd8</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/spf13/cobra" rel="noopener noreferrer"&gt;Cobra is awesome.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At Duro, my team and I made a sweet CLI tool that allows us to create microservices for our platform quickly and easily. The tool sets up a standard service configuration for TypeScript, linting, integration with our shared library, and specific Github Actions for pushing the service to the cloud. It's been really nice to have.&lt;/p&gt;

&lt;p&gt;We're constantly tweaking things with it, fixing little things and changing our configurations. We decided to use &lt;a href="https://goreleaser.com/" rel="noopener noreferrer"&gt;GoReleaser&lt;/a&gt; to help us version the tool and create the binaries and publish them to Github. It's been awesome.&lt;/p&gt;

&lt;p&gt;Until we had to distribute it.&lt;/p&gt;

&lt;p&gt;Revisions started increasing and it was a hassle trying to make sure that you have the latest version of the tool. In the spirit of "get things done", we just had everyone download it and delete it when they were done. Not a great solution, but hey, we had more things to worry about.&lt;/p&gt;

&lt;p&gt;Lately, I decided to take it upon myself to show this tool some love (and curry favor with my fellow devs) to try to manage versions of this tool via Homebrew. I didn't know the internals of how Homebrew worked, so I decided to dig in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Homebrew Basics
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiptxn9pc8qnwyflaqmpm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiptxn9pc8qnwyflaqmpm.png" alt="Homebrew logo image" width="800" height="1204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Homebrew is a package manager that allows users to install packages through a simple interface. If you need &lt;code&gt;curl&lt;/code&gt; and you don't have it, you can simply run &lt;code&gt;brew install curl&lt;/code&gt; and Homebrew will fetch it. You can even specify specific versions of a package if you need.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does Homebrew know where to get things from?
&lt;/h3&gt;

&lt;p&gt;Homebrew has a list of core packages &lt;a href="https://formulae.brew.sh/formula/" rel="noopener noreferrer"&gt;you can browse here&lt;/a&gt; and those are available when you type in &lt;code&gt;brew install&lt;/code&gt;. Each of these packages has a &lt;strong&gt;formula&lt;/strong&gt;, which is just a Ruby file that shows what the latest SHA is of a package and allows Homebrew to select the right binary based on your operating system. Here's an example of a formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Wget &amp;lt; Formula
  homepage "https://www.gnu.org/software/wget/"
  url "https://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz"
  sha256 "52126be8cf1bddd7536886e74c053ad7d0ed2aa89b4b630f76785bac21695fcd"

  def install
    system "./configure", "--prefix=#{prefix}"
    system "make", "install"
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository that this formula is stored in is called a &lt;strong&gt;tap&lt;/strong&gt;. In fact, the list of core package are stored in the &lt;a href="https://github.com/Homebrew/homebrew-core" rel="noopener noreferrer"&gt;core tap&lt;/a&gt;. This is not only tap you can have; you can create your own tap.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I create a tap and what happens when I do?
&lt;/h3&gt;

&lt;p&gt;There's standard documentation on how to &lt;a href="https://docs.brew.sh/Taps" rel="noopener noreferrer"&gt;create a tap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The short version is that when you type in &lt;code&gt;brew tap &amp;lt;tap_name&amp;gt; &amp;lt;URL&amp;gt;&lt;/code&gt;, it will go to that URL and clone the repository there and save it in &lt;code&gt;$(brew --repository)/Library/Taps&lt;/code&gt;. Then, when you type in &lt;code&gt;brew install &amp;lt;package&amp;gt;&lt;/code&gt;, it will search the core tap first and then any additional taps you've created. It will then look for the formula Ruby file and grab the latest package (or the version you specify) from the specified location in the formula and put it in Homebrew's path so you can access it.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I create a formula?
&lt;/h3&gt;

&lt;p&gt;You can create one by hand, but &lt;a href="https://goreleaser.com/customization/homebrew/" rel="noopener noreferrer"&gt;GoReleaser can do it for you&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Here's the basic config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brews:
  -
    # Name of the recipe
    #
    # Default: ProjectName
    # Templates: allowed
    name: some_app

    # Folder inside the repository to put the formula.
    folder: Formula

    # Your app's description.
    #
    # Templates: allowed
    description: "Put in description here."

    # Repository to push the generated files to.
    repository:
      owner: example
      name: some_app
      branch: brew-releases/{{ .Version }}
      token: "{{ .Env.GITHUB_TOKEN }}"
      pull_request:
        enabled: true
        base:
          owner: example
          name: some_app
          branch: master

    # NOTE: make sure the url_template, the token and given repo (github or
    # gitlab) owner and name are from the same kind.
    # We will probably unify this in the next major version like it is
    # done with scoop.

    # URL which is determined by the given Token (github, gitlab or gitea).
    #
    # Default depends on the client.
    # Templates: allowed
    url_template: "https://github.com/example/some_app/releases/download/{{ .Tag }}/{{ .ArtifactName }}"

    # Allows you to set a custom download strategy. Note that you'll need
    # to implement the strategy and add it to your tap repository.
    # Example: https://docs.brew.sh/Formula-Cookbook#specifying-the-download-strategy-explicitly
    download_strategy: GitHubPrivateRepositoryReleaseDownloadStrategy

    custom_require: './custom_release_strategy'

    # Git author used to commit to the repository.
    commit_author:
      name: goreleaserbot
      email: goreleaserbot@example.com

    # The project name and current git tag are used in the format string.
    #
    # Templates: allowed
    commit_msg_template: "Brew formula update for {{ .ProjectName }} version {{ .Tag }}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, GoReleaser will generate the Ruby formula file for you and try to commit it into the &lt;code&gt;Formula&lt;/code&gt; folder in this repository. In my case, we made our main branch protected so we had to specify the section that auto-creates a PR with the new formula.&lt;/p&gt;

&lt;p&gt;We also have a Github Action that uses &lt;a href="https://github.com/goreleaser/goreleaser-action" rel="noopener noreferrer"&gt;GoReleaser's custom action&lt;/a&gt; to trigger a release whenever a new tag is created in our repo. Now all one of us has to do is create a release with a new tag and the GitHub Action will prepare a release with the binaries and then auto-create the PR with the updated formula. Once it's merged in, Homebrew should take care of updating the revisions.&lt;/p&gt;

&lt;p&gt;Then it's just the &lt;code&gt;brew tap&lt;/code&gt; and &lt;code&gt;brew install&lt;/code&gt; combo FTW!(You might need to have a GitHub personal access token in your &lt;code&gt;HOMEBREW_GITHUB_API_TOKEN&lt;/code&gt; env variable).&lt;/p&gt;

&lt;h2&gt;
  
  
  That doesn't sound so bad! Why were you complaining about it being a pain?
&lt;/h2&gt;

&lt;p&gt;Ah, that's right. The gotcha.&lt;/p&gt;

&lt;p&gt;Homebrew uses several different methods to download/clone repos, such as &lt;code&gt;CurlDownloadStrategy&lt;/code&gt; (&lt;a href="https://github.com/Homebrew/brew/blob/master/Library/Homebrew/download_strategy.rb#L380" rel="noopener noreferrer"&gt;which does exactly what it says&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;They used to support one called &lt;code&gt;GitHubPrivateRepositoryReleaseDownloadStrategy&lt;/code&gt;. It's exactly what the name implies: it downloads releases from GitHub private repositories. At the time I was doing my research into doing this myself, there was a good amount of documentation floating around that says to use that strategy for fun and profit.&lt;/p&gt;

&lt;p&gt;Problem is, &lt;a href="https://github.com/Homebrew/brew/pull/5112" rel="noopener noreferrer"&gt;Homebrew no longer supports that strategy&lt;/a&gt;. Then &lt;a href="https://github.com/goreleaser/goreleaser/pull/1304" rel="noopener noreferrer"&gt;GoReleaser stopped supporting it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr318dlojpni7vftm0dp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr318dlojpni7vftm0dp.png" alt="Morpheus what if I told you" width="375" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screwed? Not really, thanks to some help from the community and open source software!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/goreleaser/goreleaser/issues/967#issuecomment-467354058" rel="noopener noreferrer"&gt;This comment&lt;/a&gt; in a GoReleaser issue showed me I can copy the old code from older versions of Homebrew and include them into my formula with GoReleaser.&lt;/p&gt;

&lt;p&gt;I think in the end we used &lt;a href="https://github.com/Homebrew/brew/issues/15169#issuecomment-1503860402" rel="noopener noreferrer"&gt;the recommendation made here&lt;/a&gt; with the code contained &lt;a href="https://gist.github.com/minamijoyo/3d8aa79085369efb79964ba45e24bb0e" rel="noopener noreferrer"&gt;in this Gist link&lt;/a&gt;. We put that code into the same &lt;code&gt;Formula&lt;/code&gt; folder in the repo and named it &lt;code&gt;custom_release_strategy.rb&lt;/code&gt;. That file is pointed to in the &lt;code&gt;custom_require&lt;/code&gt; field in the &lt;code&gt;brews&lt;/code&gt; section and automatically includes it in the formula file so Homebrew knows how to download the packages.&lt;/p&gt;

&lt;p&gt;Hope that helps anyone who wants to build their own CLI tool and ship it via Homebrew!&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Helpful Links:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://hackernoon.com/building-homebrew-taps-for-private-github-repos" rel="noopener noreferrer"&gt;https://hackernoon.com/building-homebrew-taps-for-private-github-repos&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/jhot/homebrew-and-private-github-repositories-1dfh"&gt;https://dev.to/jhot/homebrew-and-private-github-repositories-1dfh&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>homebrew</category>
      <category>cli</category>
      <category>goreleaser</category>
    </item>
    <item>
      <title>React Context with React Router v6.4</title>
      <dc:creator>Tim Bright</dc:creator>
      <pubDate>Sun, 27 Nov 2022 21:16:51 +0000</pubDate>
      <link>https://dev.to/40percentironman/react-context-with-react-router-v64-44je</link>
      <guid>https://dev.to/40percentironman/react-context-with-react-router-v64-44je</guid>
      <description>&lt;p&gt;I searched for a while to find how to use the Context API with &lt;code&gt;createBrowserRouter&lt;/code&gt;. What I found is that you can use &lt;a href="https://reactrouter.com/en/main/start/concepts#layout-routes" rel="noopener noreferrer"&gt;layout routes&lt;/a&gt; to wrap your components with the provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Outlet } from 'react-router-dom';
export default function ContextLayout() {
  return (
    &amp;lt;ContextProvider&amp;gt;
      &amp;lt;Outlet /&amp;gt;
    &amp;lt;/ContextProvider&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you can create a &lt;code&gt;RouteObject&lt;/code&gt; without a path that renders that layout route with the children as the components you want to wrap in the provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createBrowserRouter, RouterProvider } from 'react-router-dom';
const router = createBrowserRouter([
  {
    element: &amp;lt;ContextLayout /&amp;gt;,
    children: [
      {
        path: '/some/path',
        element: &amp;lt;SomeContextConsumer /&amp;gt;
      }
    ]
  },
  ...
]);

export default () =&amp;gt; {
  const rootElement = document.getElementById('root');
  const root = createRoot(rootElement!);
  root.render(
    &amp;lt;RouterProvider router={router} /&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! Hopefully this saves someone the time it took me to figure this out.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
