🦟 Debugging and fixing hydration issues

Photo by Gilles Rolland-Monnet on Unsplash

This is part 9 of my series on server-side rendering (SSR):

  1. πŸ€·πŸ»β€β™‚οΈ What is server-side rendering (SSR)?
  2. ✨ Creating A React App
  3. 🎨 Architecting a privacy-aware render server
  4. πŸ— Creating An Express Server
  5. πŸ–₯ Our first server-side render
  6. πŸ– Combining React Client and Render Server for SSR
  7. ⚑️ Static Router, Static Assets, Serving A Server-side Rendered Site
  8. πŸ’§ Hydration and Server-side Rendering
  9. [You are here] 🦟 Debugging and fixing hydration issues
  10. πŸ›‘ React Hydration Error Indicator
  11. πŸ§‘πŸΎβ€πŸŽ¨ Render Gateway: A Multi-use Render Server

Happy New Year, everyone and welcome back to my series on React server-side rendering (SSR)! It has been a while. I apologise for the absence; it has been a difficult time for us all during this pandemic. Perhaps I will address that fully in another post sometime; for now, let's dig back into SSR!

I have re-read all of the previous posts in this series and the notes I made on what the next entries should be. As with most software development endeavours (like all those side projects we have going on), I have lost track of what was going on and my notes did not have anywhere near as much context as I had hoped when I wrote them. So, before we dig into what is next, let's briefly recap where we were and buy me a little more time to get it together.

πŸ“œ The story so far…

This is post nine in what I thought was going to be a four post series (estimates are hard). Here are the previous entries:

  1. πŸ€·πŸ»β€β™‚οΈ What is server-side rendering (SSR)?
  2. ✨ Creating A React App
  3. 🎨 Architecting a privacy-aware render server
  4. πŸ— Creating An Express Server
  5. πŸ–₯ Our first server-side render
  6. πŸ– Combining React Client and Render Server for SSR
  7. ⚑️ Static Router, Static Assets, Serving A Server-side Rendered Site
  8. πŸ’§ Hydration and Server-side Rendering

In the entries so far we have created a React app and built ourselves a render server that provides a result we can hydrate. It is almost working beautifully, but when we tried to hydrate our SSR (server-side rendered) result, we hit a snag; our SSR result does not cleanly hydrate because the path to our logo SVG file is different between the server and the client renderings. As you may recall, for hydration to work properly, the initial render cycle of our React app on both the server and client must produce the same HTML.

So, this week, let's dig into that hydration issue with some ideas on how to debug it and how to fix it. If all goes well and I remember what my fix was going to be, we will have a successfully server-side rendered application that hydrates by the end of this post. I don't know about you, but I'm excited to find out if I can do it.

πŸ”Ž Discovering Hydration Errors

React has improved since I first started writing this series (it has been a couple of years, after all). Hydration errors now contain much more information about the error that helps us identify the problematic component – while our app is simple and therefore, a lot easier to reason about and find the source of a problem, many production apps are incredibly complex and therefore not so easy to debug.

Animation showing the app hydrated with an image placeholder rotating the center of the app instead of the image that should have loaded.
Our app after hydration failed

Back when we were last looking at this and our app hydrated without its spinning logo, here is what the hydration error looked like:

Console output showing warning that says "Prop 'src' did not match" along with the server and client values.
Hydration error in React 16.12

In this example (from an earlier version of React 16), we are told is that a src attribute did not match and we are told what the two different values are. For a case like an image that only appears in one place in our app, this is not so hard to track down, but many hydration issues are not so easy to spot.

And here is what React says about the same error today:

Console output showing warning that says "Prop 'src' did not match" along with the server and client values, and a stack of the components so that it is easy to identify which component did not render properly.
Hydration error in React 17.0

This is from React 17, though more recent versions of React 6 also provide more similar detail. This updated hydration error output not only gives us the information we had before, but also gives us a stack of components showing us exactly where in the component hierarchy the issue lives. I think you will agree that this is a vast improvement. It certainly reduces the things I was originally going to discuss about debugging hydration1.

From this more detailed error message, we can determine that our issue (as we already know from looking at the hydrated result) is that the URL for the logo is wrong; the server is setting it to an absolute file path instead of the magic sauce that the webpack build is using.

This is one of many hydration errors that can show up. Some of the more common errors relate to browser feature detection being used as conditions within components β€” since the server has no idea about the user's browser, its screen dimensions, features, or other details, any decisions it makes based on such information will likely not match the same decision when made on the client, and therefore, hydration errors. To avoid these, the initial render cycle on both the client and the server must be the same, saving any browser-specific decisions until after that first render cycle is complete. Unfortunately, if we were running production React here, we would not be guaranteed to have an obvious indication of the hydration error. In fact, this specific issue would not even be a hydration issue in production since attributes are not compared during hydration in the production build of React. However, if this were a more serious issue where the component hierarchy itself changed between server and client, the hydration failure could cause the entire application to re-render from scratch. Spotting hydration errors and fixing them can prevent serious user-facing performance issues, and since we do not get a signal during production we have to make sure we are looking for these errors during development2.

Fixing Our Image Hydration

Before we finish this post, we should really fix our image. The image URL is not working because the server handles the SVG in a very naΓ―ve way; we just use the import path, which will not match the path the client ultimately uses.

There are a few ways we can fix this and like so many things in software development, there is no single "right way" – it always depends on how much effort one wants to make and how much time we have in order to achieve a desired outcome. Here are our immediate options:

  1. Overhaul the build so that we can reuse on the server the same file paths generated by the client build.
  2. Use yarn build to generate the production site and then let the server use the same files.
  3. Introduce a delayed rendering so that the initial renders of server and client will always match.

Option 1 is where I would like us to ultimately be. It allows us to decouple the deployment of the static site and the server-side rendering setup, giving us a scalable solution. The render server at Khan Academy uses a similar to this approach and my work on that server inspired me to write this blog series in the first place.

Option 2 is what many sites do. They deploy the render server with the built client code, and as such, it always has the right paths. While we are leveraging this approach a little since our server imports code from the client folder, going all the way to having to do production builds just to test this in development is not helpful. In addition, this approach does not scale very well.

Option 3 is a very useful approach. Using a hook or stateful component to delay client-specific code until after the initial render is a versatile solution to many hydration issues. For example, if you want to add identifiers to your elements to satisfy accessibility requirements (which you should want), you can use a mechanism like this to ensure those identifiers are the same during initial render between the server and client. Those pesky feature detection issues mentioned earlier are also easily fixed with this approach. This is known around Khan Academy is using an SSR placeholder; as in rendering placeholder content during the initial render on both client and server, then replacing that with the real content on subsequent re-renders. There can be a lot of complexity here to avoid unnecessary re-rendering, but when done right, it is a useful tool in the server-side rendering toolkit.

The SSR Placeholder

In order to avoid unnecessary rendering, such as odd cascading renders where one component delays until the 2nd render, then it's children do the same, to the point where things nested n levels deep are waiting n+1 render cycles to render for the first time, we have to be smart about implementing our delayed rendering component.

For one solution, take a look at the WithSSRPlaceholder component I wrote for Khan Academy's Wonder Blocks component library, based on earlier work in our engineering team. It tracks state and makes sure that nested uses do not delay any longer than the root instance, avoiding cascading render cycles. Because the server only does a single render and does not mount the component, state changes do not get rendered on the server and we just get a single render, but in the client, the state change triggers another render and we get the update we are looking for3. It may seem tempting to just use useEffect or useState, but if you want nice reusable components that can nest happily without those aforementioned cascading renders, then some sort of context is going to be needed.

That said, useEffect and useState are perfect for our really simple app to get us hydrating, as this note in the React documentation suggests:

To exclude a component that needs layout effects from the server-rendered HTML, render it conditionally with showChild && <Child /> and defer showing it with useEffect(() => { setShowChild(true); }, []). This way, the UI doesn’t appear broken before hydration.

reactjs.org

So, to resolve the hydration error we see in our example app, let's refactor our logo rendering into a component that uses this technique.

import React, {useState, useEffect} from 'react';
import logo from './logo.svg';
import './App.css';

const SpinningLogo = (props) => {
    const [showLogo, setShowLogo] = useState(false);

    useEffect(() => {
        setShowLogo(true);
    }, [showLogo]);

    if (showLogo) {
        return <img src={logo} className="App-logo" alt="logo" />;
    }
    return null;
};
export default SpinningLogo;
import React from 'react';
import {Link, Route, Switch} from "react-router-dom";
import Router from "./Router.js";
import SpinningLogo from "./SpinningLogo.js";
import './App.css';

function App(props) {
  const {ssrLocation} = props;
  return (
    <Router ssrLocation={ssrLocation}>
      <div className="App">
        <header className="App-header">
          <SpinningLogo />
          <div className="App-links">
            <Link className="App-link" to="/">Home</Link>
            <Link className="App-link" to="/about">About</Link>
            <Link className="App-link" to="/contact">Contact</Link>
          </div>
        </header>
        <section className="App-content">
          <Switch>
            <Route path="/about">
              This is the about page!
            </Route>
            <Route path="/contact">
              This is the contact page!
            </Route>
            <Route path="/">
              This is the home page!
            </Route>
          </Switch>
        </section>
      </div>
    </Router>
  );
}

export default App;

Now we have a component, SpinningLogo, that manages some state and only renders our logo image when that state is set true. On the initial render in both server and client, it is false and so renders nothing, but on the subsequent render in the client, it is true and we get our logo.

Or at least we should. Sadly, running this refactored code causes our server to stop working altogether and we get a confusing error.

/Users/jeffyates/git/hello-react-world/client/node_modules/react/cjs/react.development.js:1476
      throw Error( "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." );
            ^
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
    at resolveDispatcher (/Users/jeffyates/git/hello-react-world/client/node_modules/react/cjs/react.development.js:1476:13)
    at useState (/Users/jeffyates/git/hello-react-world/client/node_modules/react/cjs/react.development.js:1507:20)
    at SpinningLogo (/Users/jeffyates/git/hello-react-world/client/src/SpinningLogo.js:6:37)
    at processChild (/Users/jeffyates/git/hello-react-world/server/node_modules/react-dom/cjs/react-dom-server.node.development.js:3353:14)
    at resolve (/Users/jeffyates/git/hello-react-world/server/node_modules/react-dom/cjs/react-dom-server.node.development.js:3270:5)
    at ReactDOMServerRenderer.render (/Users/jeffyates/git/hello-react-world/server/node_modules/react-dom/cjs/react-dom-server.node.development.js:3753:22)
    at ReactDOMServerRenderer.read (/Users/jeffyates/git/hello-react-world/server/node_modules/react-dom/cjs/react-dom-server.node.development.js:3690:29)
    at renderToString (/Users/jeffyates/git/hello-react-world/server/node_modules/react-dom/cjs/react-dom-server.node.development.js:4298:27)
    at renderPage (/Users/jeffyates/git/hello-react-world/server/index.js:13:31)
    at IncomingMessage.<anonymous> (/Users/jeffyates/git/hello-react-world/server/index.js:68:29)

There's no need to panic. There are three possible reasons this error suggests might be the cause of our issue:

  1. You might have mismatching versions of React and the renderer (such as React DOM's renderer)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app

If we reason through our code, we can work out what is really going on. First, we can check the server and client and verify they are both using the same versions of React and React DOM, and yes, they most definitely are. Second, from looking at the documentation and the fact that this is such a simple case, it is unlikely we are breaking the Rules of Hooks. This leaves option three, but how could we have multiple copies of React?

If you recall, we got our server working originally by importing the App component directly from our client code into the server. Of course, that component imports React from its context and therefore resolves to the client code's node module dependencies, but our server is already importing React and ReactDOM from its own node module dependencies, and voila, we have the potential for two copies of React.

To fix this, we can have the server import React and ReactDOM from the client codebase too.

require("./require-patches.js");
const http = require("http");
const express = require("express");
const React = require("../client/node_modules/react");
const {renderToString} = require("../client/node_modules/react-dom/server");
const getProductionPageTemplate = require("./get-production-page-template.js");
const App = require("../client/src/App.js").default;

const port = 3001;
const app = express();

const renderPage = (pageTemplate, reactComponent) => {
    const renderedComponent = renderToString(reactComponent);
    return pageTemplate.replace('<div id="root"></div>', `<div id="root">${renderedComponent}</div>`);
};

if (process.env.NODE_ENV === "production") {
    app.use(express.static("../client/build"));
}

app.get("/*", (req, res, next) => {
    /**
     * Production is easy. We'll load the template and render into it.
     */
    if (process.env.NODE_ENV === "production") {
        res.send(
            renderPage(getProductionPageTemplate(), <App ssrLocation={req.url} />),
        );
        next();
        return;
    }

    /**
     * During development, we're going to proxy to the webpack dev server.
     */
    if (process.env.NODE_ENV !== "production") {
        /**
         * Let's make life easier on ourselves and only accept UTF-8 when it's
         * a text/html request. We're in dev, so we don't need GZIP savings.
         */
        const headers = Object.assign({}, req.headers);
        if (req.headers["accept"] && req.headers["accept"].indexOf("text/html") > -1) {
            headers["accept-encoding"] = "utf8";
        }

        /**
         * Now call the client dev server, which we know is on port 3000.
         */
        http.get(
            {
                port: 3000,
                path: req.url,
                headers: headers,
            },
            (proxiedResponse) => {
                /**
                 * If our original request was text/html, we want to render
                 * react in there. So, let's gather that response and then
                 * render the page.
                 */
                if (req.headers["accept"] && req.headers["accept"].indexOf("text/html") > -1) {
                    let responseBody = "";
                    proxiedResponse.setEncoding("utf8");
                    proxiedResponse.on("data", (chunk) => {
                        responseBody += chunk;
                    }).on("end", () => {
                        res.send(
                            renderPage(responseBody, <App ssrLocation={req.url} />),
                        );
                        next();
                    }).on("error", e => {
                        res.status(500);
                        res.send(e);
                    });
                    return;
                }

                res.writeHead(proxiedResponse.statusCode, proxiedResponse.headers);
                proxiedResponse.pipe(res, {end: true});
                next();
            },
        );
    }
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

With React, ReactDOM and our App all coming from the client code, the hydration of our SSR result is now working!

Animated screengrab of the App we have been building, showing the rotating logo and the Home, About, and Contact links.
Our server-side rendered and hydrated application now looks the same as if it was render solely client-side

πŸŽ‰We have done it. Our first server-side rendered app that is properly hydrating. We have cut a few corners to get here, and learned a few things along the way. Hopefully, this exercise has not only highlighted the complexities of implementing successfully hydrating code, and spotting and debugging hydration issues, but it has also begun to demonstrate how complex our code can get as we try to implement a working server-side rendering solution.

Join me for the next post in this series when we leverage the knowledge we have built so far to find a server-side rendering approach that is scalable, generic, and cuts a lot less corners. In the meantime, please leave any questions or concerns in the comments – the more I code and blogs I write about this topic, the more I learn, and I am certain there are things I can learn from you too.

  1. Setting breakpoints, peeking at values inside React, etc. You know, real dirty debugging stuff – getting right down there in the dirt. []
  2. One goal with this series of posts is to eventually create a render server architecture that will make production-time detection of hydration issues easier to spot; time will tell if I achieve that goal. []
  3. For the hooks world, my colleague, Kevin Barabash has expanded this solution to use a RenderStateRoot component that sets up and manages the context, and a useRenderState hook for determining what phase of rendering a component is in []

πŸ’§ Hydration and Server-side Rendering

Featured image created from photos by Dan Gold and insung yoon on Unsplash.

This is part 8 of my series on server-side rendering (SSR):

  1. πŸ€·πŸ»β€β™‚οΈ What is server-side rendering (SSR)?
  2. ✨ Creating A React App
  3. 🎨 Architecting a privacy-aware render server
  4. πŸ— Creating An Express Server
  5. πŸ–₯ Our first server-side render
  6. πŸ– Combining React Client and Render Server for SSR
  7. ⚑️ Static Router, Static Assets, Serving A Server-side Rendered Site
  8. [You are here] πŸ’§ Hydration and Server-side Rendering
  9. 🦟 Debugging and fixing hydration issues
  10. πŸ›‘ React Hydration Error Indicator
  11. πŸ§‘πŸΎβ€πŸŽ¨ Render Gateway: A Multi-use Render Server

Over the course of this series on server-side rendering (SSR), we have tackled some interesting problems1.

In the last post on this topic, we finally combined our client app and server, giving an SSR result that looks and works a lot like the non-SSR version…or at least it seemed that way. As it turns out, we are missing a big piece of the SSR story and, I'm afraid to say, that once we add that in we will see that we still are not quite done. That piece is hydration.

ℹ️Code for this series can be found at https://github.com/somewhatabstract/hello-react-world.

πŸ™‹πŸ»β€β™‚οΈ What is Hydration?

React does a lot of things to help simplify the rendering and operation of a client-side web application. In order to do that, a root component that represents our application has to be mounted into the page. This is done via the ReactDOM.render call. It takes the component representing our application and a DOM node indicating where in the page the application will exist. In our simple web application, this looks something like this.

ReactDOM.render(<App />, document.getElementById('root'));

Without server-side rendering, the root node that we are giving here is entirely empty. When the ReactDOM.render call occurs, React fills that empty node with our application. When we have an SSR result, that node already has content in it. Instead of replacing that content, we want React to attach. running application to it. This is where hydration comes in. During hydration, React works quickly in a virtual DOM to match up the existing content with what the application renders, saving time from manipulating the DOM unnecessarily. It is this hydration that makes SSR worthwhile.

There are two big rules to hydrating an application in React.

  1. The initial render cycle of the application must result in the same markup, whether run on the client or the server.
  2. We must call ReactDOM.hydrate instead of ReactDOM.render in order to instruct React to hydrate from our SSR result.

We will get back to the first item as it is going to drive some further work once we have addressed the second; making React hydrate our SSR result.

🚰 Making our application hydrate

There are two ways we can make our page hydrate. We could either assume we will always SSR and therefore always call hydrate instead of render, or we could support both hydrate and render depending on how our application gets deployed. The benefit of the former is that we do not have to do any branching in our client-side code for the two modes; the benefit of the latter is that our application is flexible, allowing us to use the client-side application without demanding that we SSR, even in development.

In the end, it really is best to support both, so we are going to need to update our client application to understand the difference between the two states and act accordingly. So, how does our client application know which to do; hydrate or render?

There are many ways to do this. Some things that spring to mind are:

  1. Look at the element being used for the root of our application and if it has children, hydrate instead of render.
  2. Embed JavaScript in the page markup that sets a flag to specify one or the other.
  3. Use a function to perform the action and then use embedded JavaScript to change which operation that function performs.

I am sure you could think of some more. Since we already have to get the element in order to mount the React application, I am going to stick with option 1 for now (we can always change our minds if need be). Below I have included the index.js of our client application before and after adding hydrate support. In both files I have highlighted what changes. Note that we do not even have to touch our SSR implementation in order to get this working.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

const mountElement = document.getElementById('root');
const reactMountFn = (mountElement.childElementCount === 0)
    ? ReactDOM.render
    : ReactDOM.hydrate;

reactMountFn(<App />, mountElement);

Right, let's see what happens when we run our application with this updated code. First, in development mode, we start the client and the server2. If we have done this correctly, visiting the non-SSR route should use render and visiting the SSR route should use hydrate; and if we've really done things correctly, we'll never know.

Developer Mode render
Developer Mode hydrate with SSR

Oh dear; something is not looking so great. It feels like we took a step backwards here. Last time we had a server-side rendered application that looked just like the client-only version, and now we're back to not even loading the SVG asset properly. What happened?

🚱 When hydration fails

If we open the console for the version that is performing hydration, we can see a big hint to our problem.

Error in Google Chrome console reading:

Warning: Prop `src` did not match. Server: "/Users/jeffyates/git/hello-react-world/client/src/logo.svg" Client: "/static/media/logo.5d5d9eef.svg"

I had mentioned at the end of our last post that our SVG was getting the wrong path because we were not including our root React component with all the webpack magic, and this is the result. Our server-side rendered content has a different path than the React application wants to use when rendered on the client.

Did I say rendered? Don't I mean hydrated? Well, React is rendering the client application in a virtual DOM and comparing it to the content it is trying to hydrate in the page (our SSR result); if there is a mismatch, the rendered part wins. In the worst case, this can cause the entire application to re-render in the client in order for React to guarantee the client-side application is in the correct state.

These hydration warnings are, in my view, a big deal but are so easily overlooked. They are hidden away in the console messages of development builds – production builds do not raise them, React just silently deals with the situation in the way it thinks best, which could be a total re-render of your application. Not only that, but they are pretty hard to debug. This one is clear, but when it comes to others, they may just say that there's a div it did not expect; good luck finding out which div that is. Finally, if there is more than one, you will only see the second one once you fix the first, so staying on top of these is important if you want to ensure your SSR results can be used to their full potential, avoiding those costly client-side re-renders if the hydration fails.

πŸ€— Don't Panic

Of course, there's no need to panic; we have made incredible progress. We actually have a server-side rendering application that is attempting to hydrate. This is pretty fantastic and the only error we seem to have right now, the SVG path mismatch, is as much down to how our code is built using webpack as it is to do with React. Next time, we will dig into this hydration warning, work out how to fix our SVG path, and pave the way for a deeper dive into fixing hydration issues.

As always, thank you for your attention. Server-side rendering is a fun topic, in my opinion, but it can seem overwhelmingly complex3. I hope this series is proving useful in breaking apart that complexity and surfacing the sharp edges on which we can get easily caught. Let's smooth those edges down together.

Until then, be well! πŸ’™

  1. I think they are interesting – I hope you agree []
  2. Remember, last time we made it so that our SSR server gets files from the client dev server to ensure we get that good webpack magic. []
  3. it was for me when I first got started []

OzCode: Reveal With Reveal

In my last post, I revealed that I am a magician; an OzCode magician1. I also revealed the new LINQ support currently in EAP. Since that was two reveals in one, I thought that I would look at another OzCodeΒ feature today coincidentally called Reveal.

I remember this specific feature as "favourites for properties" although I am reliably informed by the OzCode team, their website, and their documentation that it is in fact called "Reveal"2. Reveal was the feature that first lured me into regular use of OzCode and if it is the only feature you use, you will still wonder how you really survived without it.

When debugging, we can spend lots of time drilling down into objects to find the value of various properties and sub-properties. This can get especially tiresome when we're looking at a few similar objects since we repeat the same steps. Although pinning certain values is helpful, it does not really solve the initial issue of drilling down to find the thing to pin.

With Reveal, we can make life much simpler by elevating the details of an object to itsΒ summary; like an on-the-fly custom ToStringΒ implementation. Not only does this help with looking at one item, but it really helps with collections of similar items. For example3:

Animated GIF showing how to use Reveal in OzCode
Animated GIF showing how to use Reveal in OzCode

Any properties that are "revealed" carry across to the rest of the debug sessionΒ and beyond;Β once you have revealed some properties, they stay revealed until you decide you do not want them to be anymore, even across debug sessions.

Animated GIF showing how the revealed properties remain revealed
Animated GIF showing how the revealed properties remain revealed

You can even see (and change) your revealed properties directly within the LINQ analysis window.

Animated GIF of using Reveal inside the new LINQ analysis feature of OzCode
Animated GIF of using Reveal inside the new LINQ analysis feature of OzCode

Finally, revealed properties propagate up the object hierarchy allowing you to surface values from deeper in your object tree. This can really be a huge time saver, especially since the revealed properties are remembered across sessions.Β No more hovering over multiple things to find what you're looking for and no more writingΒ custom ToStringΒ overrides, debug visualizers,Β or other workarounds.

Hopefully, thisΒ overview of Reveal in OzCode has demonstrated not only why I love it so much, but also how valuable it can be. I genuinely believe OzCodeΒ to be an essential tool in any .NET developer's kit, but since you may mistake me for some corporate shill, you should not take my word for it; tryΒ OzCode out for yourself with a free trial (or take part in the EAP). Stop performing workarounds and start performing magic.

  1. Read as Sean Connery as James Bond []
  2. and apparently it doesn't matter how often I tell them they are wrong []
  3. To demonstrate, I am using the handy demo app from OzCode, which you can find onΒ GitHub []

I Am an OzCode Magician and I Have a New LINQ Trick

It has probablyΒ not gone unnoticed by those whoocm_logo know me that I really like the OzCode extension to Visual Studio. Now, I have an awesome glass brick with my name etched in it as proof1.Β I am happyΒ to announce that I was recently invited to be a part of the OzCode Magician Program; an award in recognition of my genuine enthusiasm and support for OzCode over the last couple of years.

linqBug

What I really like about this is that I getΒ to occasionally preview a new feature or two. Of course, sometimes I will beΒ sworn to secrecy on what those features are, but thankfully, the current feature I have been allowed to play with is no secret at all. It was showcasedΒ in OzCode's recent webinar and recently made publicly available as an EAP2, so you can try it too. To whet your appetite, here is a sneak preview of the new magical LINQ debugging support.

numericIndicators

In this latest update to OzCode, we get someΒ reallyΒ nice visualizations of our LINQ queries, enabling us to see theΒ queries step-by-step. No more refactoring code just to see what that WhereΒ will do.

quickDatatip

The new LINQ debugging allows a user to step into a specific part of the query chain on a specific iteration and see exactly what the outcome is, and it can show you how inputs map to outputs on many of the most common LINQ operations.

detailsQueryToolWindow

At the time of writing, the EAP only supports fluent syntax LINQ but I am assured that query syntax support is on its way. So, go register for the EAP now and give it a try for yourself. It's magical!

  1. also weighty enough to be a prop in an episode of CSI []
  2. Early Access Preview []

C#6: The nameof Operator

Before discussing the `nameof` operatorΒ in C#6, I want us to consider why `nameof` exists at all. So, let's head back ten years to the heady days of 2005.

Wayne's World Flashback

When version 2.0 of the .NET framework arrived, it transitioned the fledgling platform from a sketch of what might be to a fully-formed platform that could support ongoing and futureΒ desktop and webΒ development. Since then, each release of the framework and its associated languages have added a variety of bells and whistles that simplify and enhance the way we develop.Β Among many of the concepts and types introduced by .NET 2.0 was `System.ComponentModel.INotifyPropertyChanged`, part of the enhanced data binding introduced to Windows Forms development. This interface turned out to be a workhorse and introduced many developers to a new problem; making sure the string that named a variable matched the name of an actualΒ variable.

Now, you may well object to this claim since various versions of `ArgumentException` already demanded this of developers, but I think we both know that until our tooling got smarter (like FxCop and Resharper), many of us just did not fill that argument out if we could help it. After all, theΒ stack trace would tell us where the crash happened,Β we could put something meaningful in the exceptionΒ message, and keeping that variable name up-to-date after refactoring was a pain. With the advent of `INotifyPropertyChanged` the benefit of putting the variable name in a string started to outweigh the costs.Β Quickly, patterns emerged to try and simplify this, from dubiously performant uses of reflection to build-time code generation. As tools matured, we could get refactorings that took these strings into account and warnings that could shout at us if a variable was mentioned that didn't exist. FewΒ of these were particularly elegant orΒ entirely foolproof, and none were both1.Β In addition to `ArgumentException` and `INotifyPropertyChanged`, property names would be used for logging and debugging.

In the Name of Progress

There were callsΒ for a new operator to accompany `typeof`; the new operator, `infoof`2 would provide the corresponding reflection information of a particular code construct (like `MethodInfo` or `PropertyInfo`), simplifying not just obtainingΒ the name of something, but also any reflection operation involving that something. All this use and discussion of meta-informationΒ did not go unnoticed. Eric Lippert blogged about `infoof` and why it would be useful, why itΒ was so difficult to implement, and indirectly foreshadowed where we would be today. However, amid the discusson, there was little action.

In 2012, .NET 4.5 brought us the `CallerMemberNameAttribute` type and its siblings, `CallerLineNumberAttribute` and `CallerFilePathAttribute`. These new attributes enabled developers to decorate method arguments, indicating that the appropriate piece of information wasΒ to be injected into that argument when the method wasΒ called. This fell short of an `infoof` operator, but it greatly simplified use of `INotifyPropertyChanged` (and `INotifyPropertyChanging`, introduced in .NET 3.5). Alas, argument exceptions, logging, debugging, and other uses of method, variable, and property names were left as they were, often leading to mismatched error messages, obscure data binding bugs, and other problems.

That changed in 2015 withΒ theΒ new releases of both .NET and C#, and the new `nameof` operator in C#6. The `nameof` operator is sublimely simple; in fact, its concept seems so obvious that it's a wonder it took so long to appear3. Using `nameof`, we can inject the names of variables, types, methods, events, and properties into all sorts of places at compile-time4, knowing that if we change the name, our refactoring tools can update all references with confidence. Not only that, butΒ our intent is clear; we want the name of this thing to be here and not just some string that happens to look like the name of some thing. While the `nameof` operator does not replace `CallerMemberNameAttribute`, which so deftly simplified `INotifyPropertyChanged`5, it does simplify other scenarios like throwing `ArgumentException`, logging errors, and outputting debug information.

In Conclusion

When I first contemplated writing a whole blog entry dedicated to `nameof`, I thought it was too simple a feature to warrant such focus; now I have finished, I believe `nameof` to be entirely worthy of the attention. AlongΒ with the fantastic string interpolation in C#6, I believe `nameof` is one of the simplest and most useful additions to the C#6 language. Like many C# and .NET features we now take for granted, `nameof` is a beautifully simple concept that we will come to rely upon. I believe it will save us countless hours of fixing erroneousΒ refactoring, arguingΒ over coding style and code reviews, andΒ head-scratching at spurious errors.

  1. IMHO []
  2. pronounced, "Info Of" []
  3. As is often the case in software development, we were all too busy discussing the most complex use-case we could think of rather than the one that really needed solving []
  4. unlike reflection-based solutions that do all the work at run-time []
  5. `nameof`Β does provide an alternative, more wordy alternative for that scenario []