diff --git a/content/blog/angular-components-control-value-accessor/index.md b/content/blog/angular-components-control-value-accessor/index.md index 5a507960..aedecfa9 100644 --- a/content/blog/angular-components-control-value-accessor/index.md +++ b/content/blog/angular-components-control-value-accessor/index.md @@ -70,7 +70,7 @@ export class ExampleInputComponent { With only a bit of CSS, we have a visually appealing, A11Y friendly, and quirky input component. Look, it even wiggles the unicorns! - + Now, this component is far from feature complete. There's no way to `disable` the input, there's no way to extract data out from the typed input, there's not a lot of functionality you'd typically expect to see from an input component. Let's change that. @@ -303,7 +303,7 @@ Finally, you can pass these options to `ngModel` and `formControl` (or even `for If done properly, you should see something like this: - + # Form Control Classes @@ -407,7 +407,7 @@ export class AppComponent { } ``` - + Not only do you have [a wide range of Angular-built validators at your disposal](https://angular.io/api/forms/Validators), but you're even able to [make your own validator](https://angular.io/api/forms/Validator)! diff --git a/content/blog/angular-templates-start-to-source/index.md b/content/blog/angular-templates-start-to-source/index.md index f2a863db..dd4cfd1c 100644 --- a/content/blog/angular-templates-start-to-source/index.md +++ b/content/blog/angular-templates-start-to-source/index.md @@ -54,7 +54,7 @@ While Angular templates come in many shapes and sizes, a simple but common use f

True

``` - + In this example, we are creating a template and assigning it to a [template reference variable](https://blog.angulartraining.com/tutorial-the-magic-of-template-reference-variables-3183f0a0d9d1). _This template reference variable makes `falseTemp` a valid variable to use as a value for other inputs in the same template._ It then handles that variable similarly to how a variable from the component logic is handled when referenced from the template. @@ -80,7 +80,7 @@ But there's a ~~simpler~~ ~~much more complex~~ another way show the same templa ``` - + > While this is not how the `ngIf` structural template works internally, this is a good introduction to the `ngTemplateOutlet` directive, which adds functionality to the `ng-template` tag. > @@ -129,7 +129,7 @@ Here, you can see that `let-templateVariableName="contextKeyName"` is the syntax Now let's see it in action! - + As a quick note, _I only named these template input variables differently from the context value key to make it clear that you may do so_. `let-personName="personName"` is not only valid, but it also can make the code's intentions clearer to other developers. @@ -157,7 +157,7 @@ export class AppComponent { } ``` - + > While this example is effectively not-much-more than an alternative API to `ngTemplateOutlet`, it serves as a basis for introducing into further concepts. @@ -188,7 +188,7 @@ console.log(this.myComponent.inputHere); // This will print `50` It would give you the property value on the instance of that component. Angular by default does a pretty good job at figuring out what it is that you wanted to get a reference of and returning the "correct" object for that thing. - + Despite the examples thus far having only used a string as the query for `ViewChild`, you're also able to use the ComponentClass to query for a component with that component type. @@ -222,7 +222,7 @@ Now that we've configured the `ViewChild` to read this as an `ElementRef` (a cla console.log(myComponent.nativeElement.dataset.getAttribute('data-unrelatedAttr')); // This output `"Hi there!"` ``` - + `ViewChild` isn't an only child, though (get it?). There are other APIs similar to it that allow you to get references to other items in your templates from your component logic. @@ -245,7 +245,7 @@ export class AppComponent { } ``` - + Would give you a list of all components with that base class. You're also able to use the `{read: ElementRef}` property from the `ViewChild` property decorator to get a `QueryList` (to be able to get a reference to the DOM [Elements](https://developer.mozilla.org/en-US/docs/Web/API/Element) themselves) instead of a query list of `MyComponentComponent` types. @@ -276,7 +276,7 @@ this.myComponents.changes.subscribe(compsQueryList => { }); ``` - + It might be a good idea to gain familiarity of doing this as the Angular docs give the following warning in the [`QueryList` docs](https://angular.io/api/core/QueryList#changes): @@ -356,7 +356,7 @@ export class CardsList implements AfterViewInit { Awesome, let's spin that up and… Oh. - + The cards are still grey. Let's open up our terminal and see if the `console.log`s ran. @@ -372,7 +372,7 @@ If we change the `ViewChildren` line to read: @ContentChildren(ActionCard, {read: ElementRef}) actionCards; ``` - + We'll see that the code now runs as expected. The cards are recolored, the `consoles.log`s ran, and the developers are happy. @@ -620,7 +620,7 @@ Straightforward enough example, let’s see a more difficult example: ``` - + If you look at the output of this example, you'll notice that `testingMessage` isn't rendering. This is because template reference variables bind to the view that they're present in; and as a result are unable to be accessed from parent views. @@ -645,7 +645,7 @@ In order to fix this behavior, we'd need to move the second `ng-template` into t ``` - + # The Bane of All JavaScipt Developer: Timings {#timings} @@ -732,7 +732,7 @@ export class AppComponent implements DoCheck, OnChanges, AfterViewInit { } ``` - + Looking at the console logs, you'll be left with the following messages in your console: @@ -781,7 +781,7 @@ export class AppComponent { } ``` - + Because this example does not have the `helloThereMsg` template within another view (outside of the host view), it is able to render without the errors we found when using `static: true`). Likewise, if you were to add an `OnInit` lifecycle method, you'd be able to get a reference to that template. @@ -795,7 +795,7 @@ While you might wonder "Why would you use `static: false` if you can get the acc When taking the example with the `testingMessageCompVar` prop and changing the value to `true`, it will never render the other component since it will always stay `undefined`. - + # View Manipulation {#view-manipulation} @@ -837,7 +837,7 @@ export class AppComponent implements OnInit { } ``` - + This example has a lot going on, so let's dissect it bit-by-bit. @@ -908,7 +908,7 @@ ngOnInit() { } ``` - + #### Context @@ -951,7 +951,7 @@ To get around this, we can use the `ng-container` tag, which allows us to get a ``` - + #### Move/Insert Template @@ -965,7 +965,7 @@ const newViewIndex = 0; this.viewContainerRef.move(embeddRef1, newViewIndex); // This will move this view to index 1, and shift every index greater than or equal to 0 up by 1 ``` - + Angular provides many APIs to take an existing view and move it and modify it without having to create a new one and run change detection/etc again. @@ -980,7 +980,7 @@ ngOnInit() { } ``` - + [And in fact, this is how the `createEmbeddedView` works internally](https://github.com/angular/angular/blob/e1f6d1538784eb87f7497bef27e3c313184c2d30/packages/core/src/view/refs.ts#L174): @@ -1026,7 +1026,7 @@ export class RenderTheTemplateDirective implements OnInit { export class AppComponent {} ``` - + You'll notice this code is almost exactly the same from some of our previous component code. @@ -1058,7 +1058,7 @@ export class RenderTheTemplateDirective implements OnInit { export class AppComponent {} ``` - + ## Input Shorthand {#directive-same-name-input} @@ -1091,7 +1091,7 @@ export class AppComponent {} > I want to make clear that this trick is present in all directives. If you name the input the same as the directive name, it will bind the value you're passing in to that directive name while also associating the directive with the component. No need for a separate input and directive name! - + Starting to look a bit more like the `ngTemplateOutlet`, no? Well, why not go even further! Let's lean into that! With this syntax, we can add a second input, pass an object as the context to the template we want to render, and then a template reference variable, and be able to recreate Angular's `ngTemplateOutlet`'s API almost to-a-T: @@ -1125,7 +1125,7 @@ export class RenderTheTemplateDirective implements OnInit { export class AppComponent {} ``` - + The nice part is that not only does it look like the directive from its usage, [but it's also not entirely dissimilar to how Angular writes the component internally](https://github.com/angular/angular/blob/e1f6d1538784eb87f7497bef27e3c313184c2d30/packages/common/src/directives/ng_template_outlet.ts#L35): @@ -1188,7 +1188,7 @@ export class RenderThisDirective implements OnInit { export class AppComponent {} ``` - + [Just as we previously used Angular's dependency injection (DI) system to get a reference to the `ViewContainerRef`](#embed-views), we're using DI to get a reference to the `TemplateRef` created by the `*` in the invocation of this directive and embedding a view. @@ -1206,7 +1206,7 @@ The cool part about structural directives, though? Because they're simply direct ``` - + It is for this reason that **only one structural directive can be applied to one element**. Otherwise, how would it know what order to wrap those directives in? What template should get what reference to what template? @@ -1250,7 +1250,7 @@ export class AppComponent { } ``` - + Super cool! Image we kept developing this structural directive out, but you noticed while running your test (which you should totally have 👀) that toggling the checkbox doesn't actually show anything! This is because it's running the check once on `ngOnInit` and not again when the input changes. So let's change that: @@ -1278,7 +1278,7 @@ export class RenderThisIfDirective { } ``` - + You'll notice that I removed the `OnInit` lifecycle and replaced it with an input `set`ter. We could have changed the lifecycle method to use `ngOnChanges` to listen for input changes, given that we only have one input, but as your directive adds more inputs and you want to maintain the local state, that logic can get more complex. @@ -1294,7 +1294,7 @@ update(): void { } ``` - + Here, we're using the `clear` method on the parent view ref to remove the previous view when the value is false. Because our structural directive will contain a template only used for this directive, we can safely assume that `clear` will only remove templates created within this directive and not from an external source. @@ -1393,7 +1393,7 @@ export class MakePigLatinDirective { export class AppComponent {} ``` - + This might look familiar. We're using the `$implicit` value from the context within our structural directive! However, [if you review the section we introduced that concept in](#template-context), you'll notice that the syntax here is different but similar from a template variable that would be used to bind the context from an `ng-template` tag. @@ -1429,7 +1429,7 @@ export class AppComponent {} ``` - + Just as before, we would use semicolons to split the definitions, then bind the external (as in: from the directive) context value of `original` to the local (this template) variable of `ogMsg`. @@ -1461,7 +1461,7 @@ And then call them with the following template: ``` - + This can be super useful for both providing concise APIs as well as provide further functionalities to said directive simply. Structural directives offer similar, although it comes with its own syntax and limitations due to the microsyntax API. @@ -1501,7 +1501,7 @@ export class MakePigLatinDirective implements OnInit { export class AppComponent { } ``` - + You can see that I've had to tweak our previous pig latin directive example a bit. @@ -1524,7 +1524,7 @@ Now, I remember when I was learning a lot of the structural directive stuff, I t

``` - + I was not, however, greeted by praises on my PR making this change, but rather by an error in my console: @@ -1554,7 +1554,7 @@ So if we did want to take the non-functional example above and fix it to not use ``` - + ### `as` to preserve values in template variable @@ -1586,7 +1586,7 @@ export class AppComponent { } ``` - + While this example can be seen clearly with this usage of `ngIf` , let's try to add it into our `pigLatin` example: @@ -1594,7 +1594,7 @@ While this example can be seen clearly with this usage of `ngIf` , let's try to

{{upperInUpper}}: {{msg}}

``` - + In this example, we're expecting `'upper'` to be turned into `'UPPER'` by the `uppercase` pipe, then to be passed as the input to `makePiglatinCasing` and for the `$implicit` value of that context to be assigned to a local variable `msg`. If you load this, you'll noticed that the uppercased pig lattin displays as expected but the `upperInUpper` variable (which we expected to be `'UPPER'`) is undefined. @@ -1608,7 +1608,7 @@ this.parentViewRef.createEmbeddedView(this.templ, { }); ``` - + Now that we're exporting the output with the `as`, it should show on-screen as expected. So why is this? **Well, `as` exports the outputted value that it's bound to.** In this case, we're binding the value to `casing` (because that's what `'upper'` is being passed as an input to). @@ -1818,7 +1818,7 @@ export class AppComponent { } ``` - + - We're starting with enabling `uniFor` as the structural directive name - Then we're defining an input to accept `of` as a key in the syntax (to match the `ngFor` structural directive syntax). diff --git a/content/blog/how-to-upgrade-to-react-18/index.md b/content/blog/how-to-upgrade-to-react-18/index.md index 2e181762..3ce43910 100644 --- a/content/blog/how-to-upgrade-to-react-18/index.md +++ b/content/blog/how-to-upgrade-to-react-18/index.md @@ -78,7 +78,7 @@ ReactDOM.createRoot(rootElement).render( When finished, you should be able to verify the version of React you’re using with `{React.version}` - + ## Conclusion diff --git a/content/blog/master-react-unidirectional-data-flow/index.md b/content/blog/master-react-unidirectional-data-flow/index.md index 35ad3e2d..38f6a687 100644 --- a/content/blog/master-react-unidirectional-data-flow/index.md +++ b/content/blog/master-react-unidirectional-data-flow/index.md @@ -29,7 +29,7 @@ A great example of a set of components we'll use to demonstrate unidirectionalit Let's take a look at a code sample that follows this unidirectionality first: - + As you can see we're passing the `onChange` and value props to `SimpleForm`. This keeps our state consolidated inside of the `App` component rather than split between `App` and `SimpleForm`. Once you "submit" the form, `SimpleForm` calls `onDone` which changes the state stored inside of `App`. This in turn causes a re-render of `SimpleForm`. @@ -94,7 +94,7 @@ export default function App() { } ``` - + This code works, but has some inherent complexity issues. When you start expanding this component, this idea of separating your state and having to inspect the child reference from the parent makes development more difficult. Let's take a look visually how following the application logic is now more difficult with this pattern. @@ -133,7 +133,7 @@ Understanding unidirectionality is integral to scaffolding scalable React applic Now that we have a deeper understanding of unidirectionality, here's a challenge for you: Refactor the following components to better reflect unidirectionality in this coding pad. - + The functionality of the app should be consistent with the previous version. Stuck? diff --git a/content/blog/python-list-comprehension-guide/index.md b/content/blog/python-list-comprehension-guide/index.md index 04161014..458d5015 100644 --- a/content/blog/python-list-comprehension-guide/index.md +++ b/content/blog/python-list-comprehension-guide/index.md @@ -239,7 +239,7 @@ We’ve covered a lot about list comprehension in Python today! We’re able to For example, given this sandbox code pad of a long and messy list comprehension, how can you refactor to remove all usage of list comprehensions? Avoid using `map`, `filter` or other list helpers, either. Simply use nested `for` loops and `if` conditionals to match the behavior as it was before. - + This is an open-ended question meant to challenge your skills you’ve learned throughout the article! diff --git a/content/blog/react-refs-complete-story/index.md b/content/blog/react-refs-complete-story/index.md index 3ebf19e6..b377a849 100644 --- a/content/blog/react-refs-complete-story/index.md +++ b/content/blog/react-refs-complete-story/index.md @@ -113,7 +113,7 @@ Thanks to the lack of rendering on data storage, it's particularly useful for st }, [dataRef]); ``` - + # Visual Timer with Refs {#visual-timers} @@ -145,7 +145,7 @@ Let's take the example from before, but inside of the `setInterval`, we update a Now, we'd expect to see the timer update from `1` to `2` (and beyond) as the timer continues to render. However, if we look at the app while it runs, we'll see some behavior we might not expect: - + This is because [the closure](https://whatthefuck.is/closure) that's passed to the `setInterval` has grown stale. This is a common problem when using React Hooks. While there's a simple solution hidden in `useState`'s API, let's solve this problem using mutations and `useRef`. @@ -171,7 +171,7 @@ Because `useRef` relies on passing by reference and mutating that reference, if }, [dataRef]); ``` - + > * I would not solve it this way in production. `useState` accepts a callback which you can use as an alternative (much more recommended) route: > @@ -214,7 +214,7 @@ At the start of this article, I mentioned that `ref`s are not just a mutable dat In this example, if we took a look at the `console.log` in the `useEffect`, we'd find [an `HTMLDivElement` instance](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDivElement) in the `current` property. Open the following StackBlitz and look at the console value to confirm: - + Because `elRef.current` is now a `HTMLDivElement`, it means we now have access to [the entire `Element.prototype` JavaScript API](https://developer.mozilla.org/en-US/docs/Web/API/Element#Properties). As such, this `elRef` can be used to style the underlying HTML node: @@ -230,7 +230,7 @@ Because `elRef.current` is now a `HTMLDivElement`, it means we now have access t ) ``` - + ## Alternative Syntax {#ref-function} @@ -272,7 +272,7 @@ const App = () => { ); ``` - + You might be wondering why I didn't call that property `ref` instead of `divRef`. This is because of a limitation with React. If we try to switch the property's name to `ref`, we find ourselves with some unintended consequences. @@ -297,7 +297,7 @@ const App = () => { ); ``` - + You'll notice that the `Container` `div` is not styled to have a `lightblue` background. This is because `elRef.current` is never set to contain the `HTMLElement` ref. As such, for simple ref forwarding, you cannot use the `ref` property name. @@ -325,7 +325,7 @@ const App = () => { Now that we are using `forwardRef`, we can use the `ref` property name on the parent component to get access to the `elRef` once again. - + # Class Component References {#class-ref} @@ -379,7 +379,7 @@ const App = () => { > } > ``` - + If you look at the `console.log` statement, you'll notice that it prints something like this: @@ -464,7 +464,7 @@ function App() { } ``` - + # Unidirectional Flow {#unidirectional-flow} @@ -637,7 +637,7 @@ export default function App() { } ``` - + As you can witness from the embedded demo it will focus you on the `Container` `div` when the application renders. This example does not use the `useImperativeHandle` hook but instead relies on the timing of `useEffect` to have the `ref`'s `current` already defined. @@ -680,7 +680,7 @@ export default function App() { } ``` - + > If you look in the console, you'll find the `console.log` has run when `focus()` ran! @@ -704,7 +704,7 @@ That said, you're not limited to simply the names of native APIs. What do you th }, [elRef]) ``` - + > When your focus is set to the `Container` element, try typing in the ["Konami code"](https://en.wikipedia.org/wiki/Konami_Code) using your arrow keys. What does it do when that's done? @@ -777,7 +777,7 @@ export default function App() { } ``` - + This code behaves as we might initially expect, not because we've done things properly, but instead, thanks to the nature of React's `useEffect` hook's timing. @@ -811,7 +811,7 @@ export default function App() { } ``` - + Oh no! The background is no longer `'lightblue'`! Because we delay the rendering of the `div`, `elRef` is _not_ assigned for the initial render. Then, once it _is_ rendered, it mutates the `.current` property of `elRef` to assign the ref. Because mutations do not trigger a re-render (and `useEffect` only runs during renders), `useEffect` does not have a chance to "compare" the differences in value and, therefore, run the side-effect. @@ -838,7 +838,7 @@ Confused? That's okay! So was I at first. I made a playground of sorts to help u }, [minus]); ``` - + > Open your console and take notes of what `console.log` runs when you change the respective values! @@ -907,7 +907,7 @@ But, you're probably thinking that if it accepts a function, we could pass a cal ); ``` - + > But hey! Wait a minute! Even though the `shouldRender` timing mismatch is still there, the background is being applied all the same! Why is the `useEffect` timing mismatch not causing the bug we were experiencing before? @@ -934,7 +934,7 @@ That's true. However, you _can_ combine the two behaviors to make a callback tha }, [elRef, shouldRender]); ``` - + # `useState` Refs {#usestate-refs} @@ -958,7 +958,7 @@ You can do this relatively trivially using callback refs to assign to a `useStat }, [elRef]) ``` - + Now that the `ref` update causes a re-render, you can now _**safely**_ use the `ref` in `useEffect`'s dependency array. @@ -977,7 +977,7 @@ Now that the `ref` update causes a re-render, you can now _**safely**_ use the ` }, [elNode]) ``` - + However, this comes at an offset cost of performance. Because you're causing a re-render, it will inherently be slower than if you were not triggering a re-render. There are valid uses for this, however. You just have to be mindful of your decisions and your code's usage of them. diff --git a/content/blog/rust-enums-matching-options-api/index.md b/content/blog/rust-enums-matching-options-api/index.md index 4330eb3a..8c2c871f 100644 --- a/content/blog/rust-enums-matching-options-api/index.md +++ b/content/blog/rust-enums-matching-options-api/index.md @@ -499,7 +499,7 @@ Let’s say that we have the “patch” version of a software tracked. We want How can you modify the code below to support the match version being listed out properly? - + You’ll know the code is working when you’re able to output the following: diff --git a/content/blog/understanding-the-dom/index.md b/content/blog/understanding-the-dom/index.md index 44a7c168..43df252b 100644 --- a/content/blog/understanding-the-dom/index.md +++ b/content/blog/understanding-the-dom/index.md @@ -469,7 +469,7 @@ However, as you can see, we're running `stopPropagation` on the event in the blu You can see a running example of this here: - + ### Capturing {#event-capturing} @@ -510,7 +510,7 @@ This means that when the user clicks on the red square, you'll see the following You won't see anything from the green square's `eventListener`, however. - + You'll also notice that if you click on the green square, you'll never see the `"A click handled on green using capture"` message. This is due to the `stopPropagation`, as mentioned before. The click is being registered on the red square first and then stopped on the blue square. diff --git a/content/blog/web-components-101-lit-framework/index.md b/content/blog/web-components-101-lit-framework/index.md index 8e3ef73f..bacec9f3 100644 --- a/content/blog/web-components-101-lit-framework/index.md +++ b/content/blog/web-components-101-lit-framework/index.md @@ -65,7 +65,7 @@ window.customElements.define('hello-component', HelloElement); ``` - + There are two primary differences from the vanilla JavaScript example. First, we no longer need to use the `connectedCallback` to call `render`. The LitElement’s `render` function is called by Lit itself whenever needed - such as when data changes or for an initial render - avoiding the need to manually re-call the render method. @@ -159,7 +159,7 @@ window.customElements.define('hello-component', HelloElement); ``` - + Yup, that’s all. Lit allows you to bind elements by using the `@` sign and passing the function as a placeholder to the `html` tagged template. Not only does this look much HTML-like, it handles event cleanup, re-rendering, and more. @@ -254,7 +254,7 @@ window.customElements.define('hello-component', HelloElement); ``` - + ## Attribute Reactivity @@ -292,7 +292,7 @@ export class ChangeMessageElement extends LitElement { } ``` - + # Reactive Data Binding @@ -332,7 +332,7 @@ export class FormElement extends LitElement { } ``` - + You may also notice that we’re binding both the user’s input and output to set and reflect the state. [This is exactly how other frameworks like React also expect you to manage user state](https://coderpad.io/blog/master-react-unidirectional-data-flow/). @@ -449,7 +449,7 @@ window.customElements.define('change-message-component', ChangeMessageElement); ``` - + This works because properties and attributes are both created at the same time with Lit. @@ -514,7 +514,7 @@ class TodoElement extends LitElement { } ``` - + # Passing Functions @@ -549,7 +549,7 @@ class TodoElement extends LitElement { } ``` - + You will notice that we’re using a `filter` within our `render` method. Because this logic is within the `render` method, it will run on every UI update. This is important to note in case you have expensive operations: you should avoid running those within the render method.