Fixing warnings.

reactors
Thomas Hintz 3 years ago
parent ea041f502c
commit c923fd4aef

@ -12,24 +12,24 @@ export default function Page() {
For years it was very common to see Redux used on React projects to manage application state but now it is less common to see new React projects utilizing Redux. What has changed? And does that change make sense?
</P>
<P>
Large front-end React applications usually have a lot of state to store and manage. This is usually divided into two types of state: domain specific state and component specific state. Domain specific state is state that relates to your application domain, like say an array of todo's in a todo list. Whereas component specific state is state that is needed for the functioning of an individual component or group of components, like storing what the user has entered in a text input or whether a form is valid or not.
Large front-end React applications usually have a lot of state to store and manage. This is usually divided into two types of state: domain specific state and component specific state. Domain specific state is state that relates to your application domain, like say an array of todo&apos;s in a todo list. Whereas component specific state is state that is needed for the functioning of an individual component or group of components, like storing what the user has entered in a text input or whether a form is valid or not.
</P>
<P>
React has always been good at managing state specific to a component but if state was application wide, like domain state often is, or if component state touches a large hierarchy of components, like say a theme, React was originally very unwieldy. This is where libraries like Redux became not just useful but often necessary. Redux allowed you to share state across components in a composable yet convenient way. Redux has other benefits as well but based on its real world usage in most React projects it was primarily used to make up for state management deficiencies in React. This, however, is no longer necessary.
</P>
<H2>What has changed?</H2>
<P>
In the intervening years React has introduced it's own solution to cross-cutting state: contexts. They've also introduced Redux like APIs, including reducers. In fact, much of Redux can now be replicated purely in React with just a few lines of supporting library code. React has also improved its lifecycle hooks to make working with state easier. So now using Redux to improve cross-cutting state management is no longer necessary since React can handle that itself.
In the intervening years React has introduced it&apos;s own solution to cross-cutting state: contexts. They&apos;ve also introduced Redux like APIs, including reducers. In fact, much of Redux can now be replicated purely in React with just a few lines of supporting library code. React has also improved its lifecycle hooks to make working with state easier. So now using Redux to improve cross-cutting state management is no longer necessary since React can handle that itself.
</P>
<P>
This isn't the end of the story, however. From a technical standpoint Redux can be used in a modular, contained fashion but in the real world this rarely happened because it took more discipline and boilerplate and many large React/Redux projects ended up with components being tightly coupled to the larger Redux state tree. This made it very difficult to add features or track down bugs once the app grew large, especially with multiple contributors.
This isn&apos;t the end of the story, however. From a technical standpoint Redux can be used in a modular, contained fashion but in the real world this rarely happened because it took more discipline and boilerplate and many large React/Redux projects ended up with components being tightly coupled to the larger Redux state tree. This made it very difficult to add features or track down bugs once the app grew large, especially with multiple contributors.
</P>
<P>
So not only did Redux usage lead to unmaintainable code but it was, in the relevant ways, replaced by React itself. React now can be used to create unmaintainable code in the same way Redux was but in practice it seems to be less common because it integrates more tightly. In Redux projects oftentimes all of the state would in the Redux tree which made it really easy for any component anywhere to access or modify the state which creates a big bowl of spaghetti code. Whereas in React, contexts are generally only consumed when needed which tends to cause the components that really shouldn't be using global state to keep their state more contained. This makes the code easier to work with.
So not only did Redux usage lead to unmaintainable code but it was, in the relevant ways, replaced by React itself. React now can be used to create unmaintainable code in the same way Redux was but in practice it seems to be less common because it integrates more tightly. In Redux projects oftentimes all of the state would in the Redux tree which made it really easy for any component anywhere to access or modify the state which creates a big bowl of spaghetti code. Whereas in React, contexts are generally only consumed when needed which tends to cause the components that really shouldn&apos;t be using global state to keep their state more contained. This makes the code easier to work with.
</P>
<H2>No more Redux</H2>
<P>
So from a technical standpoint Redux is no longer needed for what most people used it for and projects that don't use it often end up with higher quality code. React can be used in a similar way to Redux now which does mean that it can lead to equally poor state management so maintaining good coding practices is still important. And Redux does still have its uses and can be used to write high quality code it's just that in the past it was often used poorly and for many projects is no longer necessary.
So from a technical standpoint Redux is no longer needed for what most people used it for and projects that don&apos;t use it often end up with higher quality code. React can be used in a similar way to Redux now which does mean that it can lead to equally poor state management so maintaining good coding practices is still important. And Redux does still have its uses and can be used to write high quality code it&apos;s just that in the past it was often used poorly and for many projects is no longer necessary.
</P>
</Article>
);

@ -31,7 +31,7 @@ export default function Page() {
<i>Shows the default rendering flow of React when state is changed on the root node.</i>
</figcaption>
<P>
So let's say you run into this point of unoptimization where your app is getting janky and you've discovered that React is re-rendering expensive components even when there is no reason to, what can you do about it?
So let&apos;s say you run into this point of unoptimization where your app is getting janky and you&apos;ve discovered that React is re-rendering expensive components even when there is no reason to, what can you do about it?
</P>
<H2>Solution</H2>
<P>
@ -52,7 +52,7 @@ export default React.memo(function ExpensiveToRender(props) {
</code>
</pre>
<P>
Essentially this means that when React says "component: please render now" the component checks its cache to see if any props have changed and if they haven't changed it replies "here you go you can just use the result I calculated previously for these components". React takes that result and now the process of rendering down that part of the tree is completed without any extra work being done.
Essentially this means that when React says &quot;component: please render now&quot; the component checks its cache to see if any props have changed and if they haven&apos;t changed it replies &quot;here you go you can just use the result I calculated previously for these components&quot;. React takes that result and now the process of rendering down that part of the tree is completed without any extra work being done.
</P>
<Image
src={renderTreeMemo}
@ -63,19 +63,19 @@ export default React.memo(function ExpensiveToRender(props) {
</figcaption>
<H2>Details</H2>
<P>
It's important to be aware of how these function though. They perform a shallow comparison of props. This works well in general but if any of your props are arrays, JS objects, or anonymous functions you can run in to cases where you expect your component to be re-rendered but it isn't. For example, if you pass an array to a component and then later add an item to that array you might expect your component to be re-rendered but it isn't. This is because React only did a shallow comparison on the array and saw that it was the same array. It doesn't scan the array contents. To get React to re-render your component when you change the contents of an array you need to instead return a new array. This is true for other non primitives, like objects. In general if you use <code>React.PureComponent</code> or <code>React.memo</code> you will be better off programming in a pure functional style.
It&apos;s important to be aware of how these function though. They perform a shallow comparison of props. This works well in general but if any of your props are arrays, JS objects, or anonymous functions you can run in to cases where you expect your component to be re-rendered but it isn&apos;t. For example, if you pass an array to a component and then later add an item to that array you might expect your component to be re-rendered but it isn&apos;t. This is because React only did a shallow comparison on the array and saw that it was the same array. It doesn&apos;t scan the array contents. To get React to re-render your component when you change the contents of an array you need to instead return a new array. This is true for other non primitives, like objects. In general if you use <code>React.PureComponent</code> or <code>React.memo</code> you will be better off programming in a pure functional style.
</P>
<P>
Another issue to be aware of when using <code>React.PureComponent</code> or <code>React.memo</code> is that sometimes your component will keep getting rendered even when you think that it shouldn't be; that none of the props have changed. This is similar to the previous case but in reverse. Instead of you not passing React a new object when you should have been, you pass a prop as a new object every time when you weren't planning to. This is most commonly seen when passing object literals or anonymous functions as props. An object literal gets instantiated into a new object every time it gets executed. So even if the contents of the object literal haven't changed it still creates a new object and React isn't checking to see if the contents have changed only whether it's a new object or not. So make sure to create these objects outside the render path.
Another issue to be aware of when using <code>React.PureComponent</code> or <code>React.memo</code> is that sometimes your component will keep getting rendered even when you think that it shouldn&apos;t be; that none of the props have changed. This is similar to the previous case but in reverse. Instead of you not passing React a new object when you should have been, you pass a prop as a new object every time when you weren&apos;t planning to. This is most commonly seen when passing object literals or anonymous functions as props. An object literal gets instantiated into a new object every time it gets executed. So even if the contents of the object literal haven&apos;t changed it still creates a new object and React isn&apos;t checking to see if the contents have changed only whether it&apos;s a new object or not. So make sure to create these objects outside the render path.
</P>
<P>
Why doesn't React just perform deep checks instead? Well this deep check can lead to bad performance which isn't what you want with a performance optimization!
Why doesn&apos;t React just perform deep checks instead? Well this deep check can lead to bad performance which isn&apos;t what you want with a performance optimization!
</P>
<P>
<code>React.PureComponent</code> isn't the only way to control when your class component renders: React also provides the lifecycle method <code>componentShouldUpdate</code>. With it you can explicitly tell React when to render the component. Generally though this method is discouraged and React recommends using <code>React.PureComponent</code>.
<code>React.PureComponent</code> isn&apos;t the only way to control when your class component renders: React also provides the lifecycle method <code>componentShouldUpdate</code>. With it you can explicitly tell React when to render the component. Generally though this method is discouraged and React recommends using <code>React.PureComponent</code>.
</P>
<P>
In summary, if you run in to performance bottlenecks with rendering then start by using <code>React.PureComponent</code> or <code>React.memo</code> and programming in a pure style. While there are cases where they aren't the solutions they are generally a good starting point. I've written more detailed articles about when to use both <code>React.PureComponent</code> and <code>React.memo</code>.
In summary, if you run in to performance bottlenecks with rendering then start by using <code>React.PureComponent</code> or <code>React.memo</code> and programming in a pure style. While there are cases where they aren&apos;t the solutions they are generally a good starting point. I&apos;ve written more detailed articles about when to use both <code>React.PureComponent</code> and <code>React.memo</code>.
</P>
</Article>
);

@ -9,18 +9,18 @@ export default function Page() {
author="Thomas Hintz"
>
<P>
White-labeling allows you to utilize one code-base across multiple brands or "skins". With React projects there are multiple ways to achieve this. The two main techniques are at compile time or at run time. The technique you use will depend on your application goals. For the Alpha Centauri Farming game we utilized compile time white-labeling but for other projects we've used run time white-labeling. In this article we will be specifically discussing run time white-labeling in React environments.
White-labeling allows you to utilize one code-base across multiple brands or &quot;skins&quot;. With React projects there are multiple ways to achieve this. The two main techniques are at compile time or at run time. The technique you use will depend on your application goals. For the Alpha Centauri Farming game we utilized compile time white-labeling but for other projects we&apos;ve used run time white-labeling. In this article we will be specifically discussing run time white-labeling in React environments.
</P>
<H2>Goal</H2>
<P>
The main goal of white-labeling is to be able to use the same code base while having interchangeable assets that can be selected at run time, like say based on the domain name of the site being served. So ideally your React code does not change at all across the different "labels" and the label can be set in one place and the rest of your React application will automatically utilize it.
The main goal of white-labeling is to be able to use the same code base while having interchangeable assets that can be selected at run time, like say based on the domain name of the site being served. So ideally your React code does not change at all across the different &quot;labels&quot; and the label can be set in one place and the rest of your React application will automatically utilize it.
</P>
<H2>Implementation</H2>
<P>
With React we actually have a built in mechanism that makes this really easy: React contexts. If we create a context for our labeling then all we have to do is set the label at the top of the component hierarchy and the rest of the application can just utilize the selected label. This is similar to how themeing is often done in React.
</P>
<P>
To make this even easier I've packaged up the context and its providers and consumers into an npm package: <A href="https://code.thintz.com/react-whitelabel/about/">react-whitelabel</A>.
To make this even easier I&apos;ve packaged up the context and its providers and consumers into an npm package: <A href="https://code.thintz.com/react-whitelabel/about/">react-whitelabel</A>.
</P>
<P>
So how do we use this package to white-label our React app? Here is a basic example:
@ -74,10 +74,10 @@ const Header = withWhiteLabelContext(HeaderComponent);`}</code></pre>
To see a fully working example check out the <A href="https://code.thintz.com/react-whitelabel/about/">docs</A>.
</P>
<P>
So how does this example work? First we setup our labels. This is just a Javascript object where each key maps to a label. Each label is also an object made up of referenceable keys. The <code>WhiteLabelProvider</code> then takes the labels and the selected label as input and then provides the selected label's object to the rest of the app. This object is accessible using a <code>WhiteLabelConsumer</code> or the <code>withWhiteLabelContext</code> wrapper. If we then made the selectedLabel dynamic, say via calling <code>window.location.hostname</code>, then we would have a fully run time dynamic white-label.
So how does this example work? First we setup our labels. This is just a Javascript object where each key maps to a label. Each label is also an object made up of referenceable keys. The <code>WhiteLabelProvider</code> then takes the labels and the selected label as input and then provides the selected label&apos;s object to the rest of the app. This object is accessible using a <code>WhiteLabelConsumer</code> or the <code>withWhiteLabelContext</code> wrapper. If we then made the selectedLabel dynamic, say via calling <code>window.location.hostname</code>, then we would have a fully run time dynamic white-label.
</P>
<P>
Also note that we are using the selected label's name as a class name in a top level div. This allows us to use the white-labeling with our CSS assets just by selecting based on the label name like <code>{`.cars a { ... }`}</code>.
Also note that we are using the selected label&apos;s name as a class name in a top level div. This allows us to use the white-labeling with our CSS assets just by selecting based on the label name like <code>{`.cars a { ... }`}</code>.
</P>
<P>
While the <A href="https://code.thintz.com/react-whitelabel/about/">react-whitelabel library</A> is not necessary for React run time white-labeling it does make it easier and more maintainable. If you implement it yourself you will likely do the same thing the library already does for you. If your interested learning more about react-whitelabel feel free to checkout the <A href="https://code.thintz.com/react-whitelabel/about/">docs</A> or the <A href="https://www.npmjs.com/package/react-whitelabel">npm page</A>.

Loading…
Cancel
Save