React Design Patterns and Best Practices
I read a “react design patterns and best practices” book a while ago. And i want to share with you what i learned and what i knew already. First thing first, I may have made a few mistake. If you find a mistake, please correct me.
> React is a declarative programing language. The most important thing; Is the work done? It doesn’t matter how it’s done. Functional programing is a declarative programing paradigm, where side-effects are avoided.
> Immutable objects are much simper compared to the components and their instances and contain only the information.
> React DOM is the glue between React and the DOM. When you want to show your react component on DOM u need to use this ReactDOM.render(); from React Dom.
> Higher order functions are functions that accept function arguments or return a function.
getLabel is a higher order function.
A higher-order component (HOC) is an advanced technique in React for reusing component logic. Concretely, a higher-order component is a function that takes a component and returns a new component.
> Every time the state changes React runs the render function again, so there’s no need for us to do anything other than setting the new state.
However, in some cases, we may want to perform some operations when the state is updated, and React provides a callback for that;
If we pass any function as a second parameter of the setstate, it gets fired when the state is updated, and the component has been rendered. The setstate function should always be considered asynchronous. You can control state chages log with react-lumberjack package.
PropTypes exports a range of validators that can be used to make sure the data you receive is valid. And propTypes are only active development mode for performance reason. We can use react-docgen packagefor extract information from React components.
> storybook package is a development environment for UI components. It allows you to browse a component library, view the different states of each component, and interactively develop and test components.
> react-refect package is a declarative and composable way to fetch data for React components.
> We can move into something that helps us automate the form creation, avoid writing a lot of boilerplate, and keep our code much cleaner with react-jsonschema-form
> For a UI library such as React, it is crucial to provide an easy way for developers to create and manage animations. React comes with an add-on, called
react-addons-css-transition-group, which is a component that helps us build animations in a declarative way. Again, being able to perform operations declaratively is incredibly powerful, and it makes the code much easier to reason about and share with the team.
react-motion, a third-party library that makes creating complex animations even easier. we can apply in the browser to draw icons and graphs is Scalable Vector Graphics (SVG). SVG is great, because it is a declarative way of describing vectors and it fits perfectly with the purposes of React.
> Styling is most important thing is ui world. And React documentation suggests developers use inline styles to style their React components. But inline styling comes a few problem. One of theme; working with inline styles is debugging. In fact, we tend to use class names to find elements in the browser DevTools to debug and check which styles have been applied. With inline styles, all the styles of the items are listed in their style attribute, which makes it very hard to check and debug the result.
For example, the button that we created earlier in this section is rendered in the following way:
<button style="color: palevioletred; background-color: papayawhip;">Click me!</button>
By itself, it does not seem very hard to read, but if you imagine you have hundreds of elements and hundreds of styles, you realize that the problem becomes very complicated.
But of course react world have got a few solutions. One of them; radium. Radium is a set of tools to manage inline styles on React elements. It gives you powerful styling capabilities without CSS. We can use pseude css or media queries.
> If you feel that inline styles are not a suitable solution for your project and your team, but you still want to keep the styles as close as possible to your components, there is a solution for you, called CSS Modules.
To divide the application into small modules that you can import whenever you need them, while still creating a big bundle for the browser, you can use a tool such as Browserify or Webpack. These tools are called module bundlers, and what they do is load all the dependencies of your application into a single bundle that can be executed in the browser, which does not have any concept of modules (yet).
And you can also use styled-components package for styling your components.
> Writing an isomorphic application means building an application that looks the same on the server and the client.
> A Universal application is an application that can run both on the server and on the client-side with the same code.
> One of the main reasons we may want to render our applications on the server-side is Search Engine Optimization (SEO). In fact, if we serve an empty HTML skeleton to the crawlers of the main search engines, they are not able to extract any meaningful information from it. React, we can render our components on the server-side and serve the content of our applications to the crawlers in such a way that it is easy for them to understand and index the content.
We all love client-side applications, because they are fast and responsive, but there is a problem: the bundle has to be loaded and run before users can take any action on the application.
If we render our website on the server-side instead, and the users start seeing some of the content as soon as they hit the page, they are more likely to stay, even if they have to wait the same amount of time before doing anything for real because the client-side bundle has to be loaded regardless of the SSR.
This perceived performance is something we can greatly improve using server-side rendering, because we can output our components on the server and return some information to the users straight-away.
We can use express for SSR. Express is a web application framework for Node.js that allows you to spin up robust APIs and web servers in a much easier and cleaner way. It is a lightweight package that does not obscure the core Node.js features.
> Next.js, which makes it incredibly easy to generate Universal applications without worrying about configuration files. It also reduces the boilerplate a lot.
> When React has to display a component, it calls its render method and the render methods of its children recursively. The render method of a component returns a tree of React elements, which React uses to decide which DOM operations have to be done to update the UI.
Whenever a component’s state changes, React calls the render methods on the nodes again and it compares the result with the previous tree of React elements. The library is smart enough to figure out the minimum set of operations required to apply the expected changes on the screen. This process is called reconciliation and it is managed transparently by React. Thanks to that, we can easily describe how our components have to look at a given point in time in a declarative way and let the library do the rest.
> React gives us a tool called key which we can use to help the library figure out which elements are changed and which ones have been added or removed.
Using key is simple, we have to add a unique key attribute to each one of the items in the list. It is important for the value of the key attribute not to change on each render, because React will compare it with its previous value to decide if the element is new or if it is an existing one.
> React, has to fire the render methods of all the components and compare the results with the previous ones.
If nothing changes, no changes will be made in the DOM, which is great. But if our render methods do complex operations, React will take some time to figure out that no operations have to be done, which is not optimal.
We surely want our components to be simple and we should avoid doing expensive operations inside the renderer. However, sometimes we simply cannot manage this and our applications become slow, even if the DOM is not touched at all.
React is not able to figure out which components do not need to be updated but we have a function that we can implement to tell the library when to update a component or not.
The method is called
shouldComponentUpdate and if it returns
false, the component and all its children's render methods are not called during an update of its parents.
> There are different things we can do to find out which components do not need to be updated. One of the easiest is to install a third-party library that can provide the information automatically. like why-did-you-update.
> Immutability, Monitoring tools and some of babale plugings(like Babel plugins) that we can apply to our codebase to monitor and improve the performance.
> Testing is very important while developing an applications. Testing web UIs has always been a hard job. From unit to end-to-end tests, the fact that the interfaces depend on browsers, user interactions, and many other variables makes it difficult to implement an effective testing strategy.
If you’ve ever tried to write end-to-end tests for the Web, you’ll know how complex it is to get consistent results and how the results are often affected by false negatives due to different factors, such as the network. Other than that, user interfaces are frequently updated to improve experience, maximize conversions, or simply add new features.
Developers tend to focus on the feature they are currently implementing and sometimes it is hard to know if other parts of the application are affected by those changes. Tests help to avoid regressions because they can tell if the new code breaks the old tests. Greater confidence in writing new features leads to faster releases.
Jest is an all-in-one testing framework solution, maintained by Christopher Pojer from Facebook and contributors within the community, and aims to give you the best developer experience; but you can decide to create a custom setup with Mocha as well. We will look at both ways of building the best test environment.
There are different techniques that we can use to write tests, and one of the most popular ones is Test Driven Development (TDD). Applying TDD means writing the tests first and then writing the code to pass the tests.
> Most of the time, whenever we test components, the most important thing for us is that the output is correct and that it does not change unexpectedly. There is a new feature introduced in Jest that helps with this problem and it’s called Snapshot Testing.
Snapshots are pictures of the component with some props at a given point in time. Every time we run the tests, Jest creates new pictures and it compares them with the previous ones to check if something has changed.