-
Notifications
You must be signed in to change notification settings - Fork 25
Lesson 4.1
This lesson will teach you the following:
Optimizing application performance is key for developers who are mindful of keeping a user’s experience positive to keep them on an app and engaged. In React applications, our applications UI start out as very performant, however, as an application grows, developers may encounter some performance issues.
Before trying to optimize a React application, it is important to know how React updates its UI which will help you troubleshoot React performance problems.
When we create a rendered component:
- React creates a virtual DOM for its element tree in the component.
- When the state of the component changes, a virtual DOM tree is created and compared with the previous render.
- Updates the changed element in the actual DOM if a change has occurred.
- This process is called diffing.
This sounds great, and is great because it speeds up the UI render time. However, this concept can also slow down a very large, complex app because of how intrinsically React re-renders components.
When a component re-renders, it tries to re-render all descendants (child components), regardless of whether they're being passed a particular state variable through props or not. This can cause unnecessary re-rendering of child components which in turn in a very large, complex UI create performance issues.
Re-rendering of a component (parent or child) does not mean it will be repainted. Re-rendering just means the code for each component will be run and then “reconciliation” will determine if any changes to the actual DOM need to be made (Virtual DOM vs Actual DOM). Painting (e.g. repainting) to the browser is very expensive from a performance point-of-view so that is why React has the Virtual DOM in the first place. All this child component re-rending can still affect performance still takes if your React application is large and complex enough. So be mindful of the child components that are being rendered in a component that will need state changes.
Specifying Component Types: PropTypes and TypeScript
As we know, React components are JavaScript functions that return React elements. These determine what will be added to the DOM. And just like functions, React components can receive arguments called props, which can result in dynamic returned elements.
Props can be of any data type, but the expected data type for components can differ which can lead to unexpected results at times. So how do we specify the type of data that our component should expect?
The two main ways are PropTypes and TypeScript. Despite having similar purposes, these two methods differ in how they work. We’ll cover what these tools are, understand their differences, and, lastly, try some advanced ways of using them.
PropTypes is a runtime type-checking tool for props in React applications. Since React 15.5, the PropTypes utility is available through the prop-types package.
With PropTypes, you can define the types of props expected in a component, like stating whether props are required or optional. When you pass a different type to a component or skip a required prop, you will get a warning in the JavaScript console.
import PropTypes from 'prop-types'
const Card = ({ description, type, id }) => {
return <span>Notification</Notification>
}
Card.propTypes = {
description: PropTypes.string.isRequired,
type: PropTypes.oneOf(["error", "warning", "success"]),
id: PropTypes.string.isRequired
}
Note that PropTypes only provides warnings during development. If an unexpected type is received while using the production version of your application, the console will not print any warnings.
Using TypeScript with React allows you to add typings to your props that will be verified at compile time. TypeScript compiles back to JavaScript because that’s what the browser understands.
Before using TypeScript in your React application, you may need to provide the necessary dependencies and configurations. For example, if you’re using Create React App, you can follow the documentation to add TypeScript support in your existing application:
https://create-react-app.dev/docs/adding-typescript/
Here’s the TypeScript interpretation of the PropTypes definition above:
type Props = {
description: string;
type: "error" | "warning" | "success";
id: string;
}
const Card = ({ description, type, id }: Props) => {
return <span>Notification</span>
}
You can do a whole lot more with TypeScript compared to PropTypes, so your best bet to learn more about TypeScript is with the docs:
https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html
Many companies use TypeScript with their React applications so it would be a great next step in your learning journey.
Software testing is the process of evaluating and verifying that a software product or application does what it is supposed to do. The benefits of testing include preventing bugs, reducing development costs, and improving performance.
There are many different types of software testing:
- Unit testing: Validating that each software unit performs as expected. A unit is the smallest testable component of an application.
- Integration testing: Ensuring that software components or functions operate together.
- End-to-end testing (E2E): This type of testing approach starts from the end user’s perspective and simulates a real-world scenario.
- Performance testing: Testing how the software performs under different workloads. Load testing, for example, is used to evaluate performance under real-life load conditions.
- Usability testing: Validating how well a customer can use a system or web application to complete a task.
Writing tests is like buying stocks. You may pay a big price up-front, but you will continue to reap the dividends for a long time. As in finance, the kind of investment you will make—and whether you will make it—depends on when you need the money back.
As your projects grow in size and scope, you will end up returning to make small and large changes to code that you've already written. Often, it is during this process that bugs begin to be introduced.
Automated testing can help with this. With automated tests, you will write more code to run your original code, ensuring that the original code works as intended. Writing tests can help you develop new functions and can future-proof your existing functions so that they don't break.
TDD, is a philosophy of first determining what you want your code to do and writing tests that your code will need to pass, and then writing the code.
Test-driven development benefits you, the developer, in the following ways:
- It helps you fully understand the requirements for your function because you have to express them by writing test code. This also helps other people understand your code.
- It helps you relax when code doesn't work. This attitude will help you think more clearly when debugging.
- It helps you fearlessly refactor and improve your code when you need to, because the tests will let you know if you break anything.
- It helps you frequently experience the joy of working code, because getting a test to pass feels great.
- TDD often takes place at the level of individual functions.
Jest is a JavaScript testing framework developed by Facebook. It includes both an assertion library and a test runner. an assertion library is a tool that will help check for equality between the actual and expected outputs from a function a test runner runs the tests so that you can easily run a complete set of tests whenever you update your code Other assertion libraries are Chai, and test runners (aka testing environments) are Mocha.
React Testing Library is a modern tool for testing the UI output of React components. The library's API of tools allows you to write tests that simulate actual users' behaviors with your components and urges you to focus on the user when writing tests.
For many years, it has been common for teams to test their components by focusing on the code's implementation details. But testing from the user's perspective is much more efficient and productive.
The DOM Testing Library is a collection of tools to make our lives easier when our goal is to test our applications' UI from real users' perspectives. The library encourages you to select DOM elements in ways that are available to all users.
The DOM Testing Library is normally not used as a standalone testing library but used as a wrapper with other testing libraries that use a framework (React, Angular, Vue, Svelte, etc) that interact directly with the DOM. The React Testing Library builds on top of DOM Testing Library by adding APIs for working with React components.
- Inside the
src/
directory, create a new folder namedcomponents/
- Move the following files into the
components/
directory-
AddTodoForm.js
-
InputWithLabel.js
-
TodoContainer.js
(stretch goal - you may not have this in your files) -
TodoList.js
-
TodoListItem.js
- Any CSS modules associated with the components above
-
- Open
src/App.js
- Update the import path for
TodoContainer.js
(stretch goal)
If you're using NPM, run
npm install --save prop-types
instead
yarn add prop-types
Documentation: https://reactjs.org/docs/typechecking-with-proptypes.html
-
Open
AddTodoForm.js
-
Import
PropTypes
from the "prop-types" package -
Below the
AddTodoForm
function, define thepropTypes
property of that function as a new object- Inside the object, define a property with key
onAddTodo
(prop name) and valuePropTypes.func
(function data type)
- Inside the object, define a property with key
-
Run your application and view in browser
- Verify that your Todo List still appears correctly with no console errors
Repeat the steps above for each of the following components, be sure to use the appropriate key/value pairs depending on the
props
for each:
- Verify that your Todo List still appears correctly with no console errors
Repeat the steps above for each of the following components, be sure to use the appropriate key/value pairs depending on the
-
InputWithLabel.js
-
TodoContainer.js
(stretch goal) if you don't have aTodoContainer.js
, useapp.js
-
TodoList.js
-
TodoListItem.js
View Instructions: https://github.com/Code-the-Dream-School/ctd-jest-unit-testing-practice