Skip to content
Home » META » Meta Front-End Developer Professional Certificate » Advanced React » Week 3: JSX and testing

Week 3: JSX and testing

Understand JSX in depth and discover advanced patterns to encapsulate common behaviour via higher-order components and render props. Then, learn how to test and debug your application.

Learning Objectives

  • Define the types of children within JSX
  • Use JSX to apply React component composition with children.
  • Describe the process and purpose of creating higher-order components.
  • Describe the process and purpose of creating render props.
  • Write a test for a React application using Jest and React Testing Library.

JSX Deep Dive


Video: JSX, Components and Elements

JSX is a syntax extension to JavaScript that React uses to describe what the UI should look like. It is a more powerful abstraction that combines both markup and business logic into an entity called a component.

When React analyzes the rendering methods from all the components, it takes the whole JSX tree and creates an intermediary representation. This representation is another tree similar to the original, but where each node instead of being JSX is a plain object describing a component instance or DOM node and its desired properties. This plain object is what React defines as an element.

An element is just a way to represent the final HTML output as a plain object. It consists primarily of two attributes, type and props. Type defines the type of node such as a button and props encompasses all the properties the component receives in a single object.

The type of an element can also be a function corresponding to a React component. When React sees an element with a function type, it will know to ask that component what element it renders to with the given props. React will keep repeating this process until it knows the underlying DOM tag elements for every component on the page.

Once React finishes the process of identifying all user defined components from the tree of elements, it will convert them into DOM elements. The result is what is generally known as the virtual DOM.

When there is a new change in the UI, React will take all the JSX and produce a new UI representation as a tree of elements. It will then compare it with the previous representation that is kept in memory. React will calculate the difference in the tree and apply the minimum number of changes to the underlying DOM nodes in order to process the update.

This is the beauty of the React declarative programming model. React takes care of updating the DOM efficiently, while developers can focus on describing what the UI should look like.

JSX, Components, and Elements in React

JSX

JSX is a syntax extension to JavaScript that allows developers to write HTML-like code within JavaScript files. JSX is not required to use React, but it is a popular choice because it makes it easier to write and maintain React code.

JSX code is converted to plain JavaScript objects by the React compiler. These objects are called React elements.

Components

A React component is a reusable piece of UI that can be rendered to the DOM. Components can be created using either JSX or plain JavaScript.

JSX components are created using the function keyword. The name of the function is the name of the component. The function takes one argument, which is an object of props. Props are used to pass data to the component.

Plain JavaScript components are created using the React.createClass() method. The createClass() method takes an object as its argument. The object can contain properties such as render(), componentDidMount(), and componentWillUnmount().

Elements

A React element is a plain JavaScript object that represents a DOM node. Elements are created using the React.createElement() method. The createElement() method takes three arguments: the type of the element, the props for the element, and the children of the element.

The type of the element can be a string, which represents the name of a DOM node, or a function, which represents a React component.

The props for the element are an object of key-value pairs. The keys are the names of the props, and the values are the values of the props.

The children of the element can be other elements, strings, or numbers.

Example

The following code is an example of a React component written in JSX:

JavaScript

function Button(props) {
  return (
    <button onClick={props.onClick}>
      {props.text}
    </button>
  );
}

The Button component takes two props: onClick and text. The onClick prop is a function that is called when the button is clicked. The text prop is the text that is displayed on the button.

The Button component returns an element that represents a <button> DOM node. The onClick prop is passed to the <button> element as the onClick attribute. The text prop is passed to the <button> element as the text content.

The following code is an example of how to render the Button component:

JavaScript

const element = <Button onClick={() => console.log('clicked!')} text="Click me!" />;
ReactDOM.render(element, document.getElementById('root'));

The ReactDOM.render() method renders the element to the DOM element with the ID root.

Conclusion

JSX, components, and elements are the fundamental building blocks of React. By understanding these concepts, you can start building your own React applications.

Which of the examples below are valid types for Elements? Select all that apply.

type: “button”

That’s correct. This is an example of how React specifies a ‘type’ attribute when performing a tree transformation with simple DOM nodes.

type: DeleteButton

Where DeleteButton is a React component.

That’s correct. React would identify a component named DeleteButton as a function and ask that component what element it renders to, with the given props.

type: “div”

That’s correct. This is an example of how React specifies a type attribute when performing a tree transformation with simple DOM nodes.

At this point, you may be wondering
how to define what JSX actually is. And it may not be entirely clear how
react works with JSX to describe a UI and produce a user friendly and effective app. Well, let’s explore these
concepts in a bit more detail. In this video, you’ll learn how
React uses JSX to describe a UI, the differences between components and
elements and the general concepts behind
the React declarative model. The Little Lemon restaurant owners have
been happy with their original website for a long time. But as they have grown as a business,
they now want to add more features, functionality, analytics and
user interactivity. They are noticing that the original
website was built in a way that means there are many limitations when it
comes to these types of enhancements. After seeking some advice, they have concluded that they should
develop an app using JSX and React. They want to understand more about JSX and
React so that they can build a rationale
into their business plan. So let’s get started with JSX. JSX is a syntax extension to
JavaScript that React uses to describe what the UI should look like. However, even though JSX looks like HTML, it’s essentially a more powerful
abstraction that combines both markup and business logic into an entity
called a component. So what is really happening from
the moment you write JSX in your render function until Reacts creates
the desired assets for your pages? To understand all the steps involved, you need to be introduced to
the concept of elements in React. By now, you already have a good
understanding of components and how your entire UI is
represented by a tree of them. You also know that the final
web pages that React produces are nothing more than pure HTML,
CSS, and JavaScript. When react analyzes your rendering
methods from all your components, it takes the whole JSX tree,
starting from the root and creates an intermediary representation. This representation is essentially
another tree similar to before, but where each node instead of being
JSX is a plain object describing a component instance or dom node and
its desired properties. This plane object is what
React defines as an element. An element is just a way to represent
the final HTML output as a plain object. It consists primarily of two attributes,
type and props. Type defines the type of
node such as a button and props encompasses all the properties
the component receives in a single object. Observe how the elements can be nested as
in the button example via the children property. When react creates the entire
element tree starting from the root, the root element specifies all the child
elements as the children prop. And each child element does the same thing
until it reaches the end of the tree. What is important about this new
structure is that both child and parent elements are just descriptions and
not actual instances. In other words, they don’t refer
to anything on the screen when you create them,
they’re just objects after all. But these objects are easy to traverse and of course are simpler than
the actual DOM elements. So far,
you have been introduced to an example of a tree transformation with
simple DOM nodes like a button. In the element tree, this is specified
as the type property, but the type of an element can also be a function
corresponding to a React component. Imagine you have created a component
to encapsulate the traditional HTML button named Submit button. In this case, the type property of the element will
point to the name of the component. This is the fundamental idea of React,
both user defined components and dom nodes can be nested and
mixed with each other in the elementary. For example,
if you were creating a log out process for the Little Lemon restaurant app, you could
do this with a log out component in JSX. In this log out component, The JSX would translate to
the following tree of elements. That allows you to mix and match
components and dom elements as the type property without worrying about whether
Submit button renders to a button, a diff or something else entirely. This keeps components
decoupled from each other, expressing their relationships
through composition. When react sees an element with a function
type like the submit button, it will know to ask that component what element
it renders to with the given props. So React will ask Submit button
again what it renders to and it will transform that into an element. React will keep repeating this process
until it knows the underlying DOM tag elements for
every component on the page. Once React finishes the process of
identifying all user defined components from the tree of elements,
it will convert them into DOM elements. The result is what is generally
known as the virtual DOM. A JavaScript alternative
representation of the real DOM. Now, what are the steps involved when
there is a new change in your UI? First, React will take all your JSX and produce a new UI representation
as a tree of elements. Second, it will compare
it with the previous representation that is kept in memory. Third, it will calculate the difference
in a tree, recall that since each node in the tree is a JavaScript object,
this diffing operation is very fast. And finally based on that difference, it
will apply the minimum number of changes to the underlying dom nodes in order
to process the update, and that’s it. You are probably starting to appreciate
the beauty of the React declared of programming model. In this video, you have learned how
react uses JSX to describe a UI, the differences between components and
elements and the general concept behind
the React declarative model. You have also seen the react transforms
your JSX into an internal tree of elements, which are just
JavaScript objects. And it is that lightweight representation
that lets React update your UI in a predictable way while being fast enough
for high performance applications.

Video: The importance of performance to software development

Performance is a critical aspect of software development. Small changes can make a big difference in the performance of an application. React is a popular JavaScript library that is known for its efficient rendering. Engineers should look for bottlenecks in their code and refactor it to improve performance. They should also use established design patterns to improve performance.

Interesting about performance it’s one of these
things that you can make it or break it with
just one line of change. Of course, sometimes it’s possible that in order to
improve the performance, you have to rewrite an entire
application and start over. But sometimes small changes
make a big difference. My name is Murtadha.
I’m a software engineer at Meta based in Seattle office. At Meta we really tried to think about the different
diversity and the different backgrounds
that users come from and what technologies they might be using to access our products. Thinking about performance
can make a big difference between gaining a user
or losing a user. Because if the application
is not performing, it’s not responsive,
it’s not fast enough, then people will not use it. It’s a big deal for
us to think about performance when we’re
developing these applications. It’s never that our applications are just performance out of
the box and we try to look for the things that can
improve their performance. Performance is usually
something that we build incrementally and we get to it by making
incremental changes. Because we may
think that this is not important and it’s more exciting to build a new feature. It’s more exciting to make
something more colorful. Performance is this
invisible thing that you may not
notice it right away, you may not be able to
show it and brag about it, but it’s actually
really important. It’s an underlying part of the application
that without it, you can’t really have
the applications. One of the things that
React does really well and it’s what has made it excel and become so popular
is that it’s very efficient in building and
rendering a web applications. What React does really
well is that it localizes the change such that if you need to
change a small text, you can only have the work for training that small
text instead of having to rewrite the entire
page or it can be very costly for a
computer to execute. We try to look for
bottlenecks and then go dive deeper into this and see why
is this components so slow? Why is it taking so long? How can we re-factor this
component to make it faster? Maybe we can delegate some of the computation to
the back-end so that we’re not incurring this cost on the user on the front-end. The engineers and the product
managers and designers, they all use the application while it’s being
developed as much as possible to be in the shoes
of a user and really feel the experience that
they’re going through when they’re using
our applications. Then once there’s
enough confidence that this application is ready after checking
all the boxes in terms of its performance, its stability, its usability, and as well as completeness. Then we release it in an
Alpha stage where there’s a small number of users trying it out so we can
get some feedback. As we gain more and more
confidence throughout the feedback cycle
than we crank it up to more users until it’s
completely released. It’s a very important part
of the requirements for an application to be
performance and usable. In order to achieve that, there are certain
design patterns and well established approaches
that engineers have developed over time
that have known to work really well and increase performance
of applications. Like using memoization or delegating part of the
processing to the back-end. I encourage you to look for
those and find ways that you can introduce these design
patterns in your application.

Video: Component composition with children

React component composition is a powerful technique for building reusable and robust components. It is based on two key features: containment and specialization.

Containment refers to the fact that some components don’t know their children ahead of time. For these components, the recommended approach is to use the children prop to pass children elements directly as their content.

Specialization defines components as being special cases of other components. For example, a confirmation dialog is a special case of dialog.

To demonstrate component composition, the author builds a generic dialog component that can be used to create a confirmation dialog for deleting a user account. The generic dialog component uses the children prop to render its content. The confirmation dialog component is a specialized version of the generic dialog component.

The author concludes by stating that component composition is an important technique for building reusable and robust React components.

Component composition with children in React

React component composition is a technique for building reusable and robust components by combining smaller components together. It is based on the idea that you can create a complex component by breaking it down into smaller, more manageable components.

One of the key features of component composition is the children prop. The children prop is a special prop that all components have, and it allows you to pass other components as children of that component.

To use the children prop, you simply pass the children components as arguments to the component that you are rendering. For example, the following code shows how to render a button component with a text label:

JavaScript

const Button = ({ children }) => {
  return <button>{children}</button>;
};

const App = () => {
  return <Button>Click me!</Button>;
};

In this example, the Button component is passed the string “Click me!” as a child. The Button component then renders that string as the text of the button.

You can also pass multiple components as children to a component. For example, the following code shows how to render a dialog component with a title and a description:

JavaScript

const Dialog = ({ children }) => {
  return <div className="dialog">{children}</div>;
};

const App = () => {
  return (
    <Dialog>
      <h1>Delete Account</h1>
      <p>Are you sure you want to delete your account? This action cannot be undone.</p>
    </Dialog>
  );
};

In this example, the Dialog component is passed two components as children: a heading component and a paragraph component. The Dialog component then renders these components as the contents of the dialog.

Component composition is a powerful technique that can help you to write more reusable and maintainable code. By breaking down your components into smaller, more manageable components, you can make it easier to add new features and fix bugs.

Here are some tips for using component composition effectively:

  • Use the children prop to pass other components as children of your components.
  • Break down your components into smaller, more manageable components.
  • Give your components meaningful names.
  • Use props to pass data between components.
  • Use state to manage the data within a component.
  • Use pure functions to write code that is easy to test and reuse.

Here is an example of how to use component composition to build a reusable navigation bar component:

JavaScript

const NavLink = ({ children, to }) => {
  return <a href={to}>{children}</a>;
};

const NavigationBar = ({ children }) => {
  return <nav>{children}</nav>;
};

const App = () => {
  return (
    <NavigationBar>
      <NavLink to="/">Home</NavLink>
      <NavLink to="/about">About</NavLink>
      <NavLink to="/contact">Contact</NavLink>
    </NavigationBar>
  );
};

In this example, the NavLink component is a reusable component that can be used to render a navigation link. The NavLink component takes two props: children and to. The children prop is the text of the navigation link, and the to prop is the URL of the page that the navigation link should link to.

The NavigationBar component is a reusable component that renders a navigation bar. The NavigationBar component takes one prop: children. The children prop is an array of NavLink components.

The App component renders the NavigationBar component and passes an array of NavLink components as children.

This is just one example of how to use component composition to build reusable and maintainable React components. By following the tips above, you can use component composition to write code that is more efficient, easier to test, and more maintainable.

Which of the statements below clearly states the definitions of Containment and Specialization? Select all that apply.

Specialization defines components as being “special cases” of other components.

That’s correct! Specialization defines components as being “special cases” ofother components. For example, the ConfirmationDialog is a special case of Dialog.

Containment refers to the fact that some components don’t know their children ahead of time. 

That’s correct! Containment refers to the fact that some components don’t know their children ahead of time. And can also be described as generic boxes, like a Dialog or Alert.

When designing React components, one of the most important
properties developers tend to overlook is
the children prop. The children prop which is a special property
all components have, is the foundation for the React powerful
composition model. Say the Little Lemon
restaurant wants to enable users to have
accounts on their app, this would mean processes would need to be built to create, manage, and delete
accounts in the app. These types of processes can
be constructed simply and efficiently using component
composition with children. In this video, you will learn why component composition is so important and how to effectively use and
appreciate the children prop. You will also learn about two key features of composition, and you’ll explore some
practical examples that will help you
understand how you can leverage it so your components are more robust and reusable. There are two main
features that enable component composition;
containment and specialization. Let’s break down these
two main features now starting with containment. Containment refers
to the fact that some components don’t know
their children ahead of time. This is especially
common for components like a sidebar or a dialog, where they delimit
a specific area in your UI to contain
other elements. You can think of them
also as generic boxes. In case you don’t know, a dialog is a type of modal
window where the rest of the UI is disabled until the modal is addressed
and interacted with. For these component boxes, the recommended approach is
to use the children prop to pass children elements
directly as their content. Let’s explore this
with a dialog example. Here you have a dialog component
which acts as the box, taking care of styling the container to make it
look like a modal window. By using the children prop, it has become a generic
component to which we can provide any valid
JSX as children. To illustrate that, the confirmation dialog
component has been defined, which uses the dialog
component and renders as children a title
and a description. This example also showcases
the second feature of component composition,
specialization. Specialization
defines components as being special cases
of other components. In this example, the
confirmation dialog is a special case of dialog. Now that you are familiar with the basics of
component composition, let’s go ahead and code an application to demonstrate
what you’ve learned. This application has been
created with Create React app. Imagine Little Lemon
would like to offer an easy way for their users to delete their account
if they want to, the goal is to build a generic dialog
component that will contain a title, a description, and a warning button to make
sure users are aware of the action’s consequences all using component composition. I have already created
two generic components, a button and an alert. The button uses the children
prop to specify its text, and the alert is a
generic box that renders an overlay in the background and a white modal in the
center of the screen. The children prop determines
the content of that modal. The first step is to
create a warning button using the specialization feature of component composition. For that, I’ll define a new component
named delete button, where I’ll render the button
component and configure its properties to have a red
color and the text delete. Then I’ll go ahead and
render the alert component. As it stands, it’s just a generic white
box or container. This illustrates the
second feature of component composition
which is containment. I can customize the content
of the box in any way I would like by just providing
JSX as its children. To fulfill the requirements
of Little Lemon, I’ll create a header
titled delete account, as well as a paragraph to inform the user
about the action. I want to state clearly
that they will miss out on the chef’s delicious recipes if they delete their account, so I’ll reflect that
in the description. Finally, the last piece is
to render the delete button as defined previously.
That wraps it up. In this video, you have learned
about a React technique called component composition
and why it is so important. You also learned how to embrace
the two key features of composition; containment
and specialization. You’ve explored some
practical examples that helps you to
create components that are more robust and reusable using the
special children prop.

Reading: Types of Children

Reading

Video: Manipulating children dynamically in JSX

The video teaches viewers how to use two React APIs, React.cloneElement and React.children.map, to manipulate children dynamically.

React.cloneElement clones and returns a new copy of a provided element. It can be used to modify children properties, add to children properties, and extend the functionality of children components.

React.children.map is a method that invokes a function in every child contained within its children prop, performing a transformation and returning a new element.

In the video, the speaker uses these two APIs to implement a row component that displays each order in a Little Lemon restaurant on its own line, with horizontal spacing between each item.

Conclusion

React.cloneElement and React.children.map are powerful tools for manipulating children dynamically. They can be used to create more flexible and reusable components.

Manipulating children dynamically in JSX

JSX is a JavaScript syntax extension that allows you to write HTML-like code within your JavaScript code. This makes it easier to create and maintain complex user interfaces.

One of the powerful features of JSX is the ability to manipulate children dynamically. This means that you can change the content of a component’s children at runtime.

There are two main ways to manipulate children dynamically in JSX:

  1. Using the React.cloneElement() API
  2. Using the React.children.map() API

Using React.cloneElement()

The React.cloneElement() API allows you to clone a React element and modify its properties. This includes the ability to add, remove, or modify the element’s children.

To use React.cloneElement(), you first need to pass it the element you want to clone as the first argument. Then, you can pass in an object containing the new props that you want to apply to the cloned element.

For example, the following code clones a button element and adds a new onClick prop:

JavaScript

const button = <button>Click Me!</button>;
const clonedButton = React.cloneElement(button, {
  onClick: () => {
    alert('You clicked the button!');
  },
});

You can then use the cloned element in your code as if it were the original element.

Using React.children.map()

The React.children.map() API allows you to iterate over the children of a React element and apply a transformation to each child.

To use React.children.map(), you first need to pass it the element whose children you want to iterate over as the first argument. Then, you need to pass in a callback function as the second argument. This callback function will be invoked for each child of the element.

The callback function takes two arguments: the current child element and the index of the child element. The callback function should return a new React element.

For example, the following code iterates over the children of a <ul> element and adds a new li element for each child:

JavaScript

const list = <ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>;

const updatedList = React.children.map(list, (child, index) => {
  return (
    <li key={index}>
      {child}
    </li>
  );
});

The key prop is used to uniquely identify each child element. This is important for React’s reconciliation algorithm to work properly.

You can then use the updated element in your code as if it were the original element.

Conclusion

Manipulating children dynamically in JSX is a powerful way to create more flexible and reusable components. By using the React.cloneElement() and React.children.map() APIs, you can change the content of a component’s children at runtime.

Which of the following operations does the React.cloneElementAPI enable a parent to perform? Select all that apply.

Modify children properties

That’s correct! Props in React are immutable objects, so onceReact.cloneElement has created a copy of the element it can then modify the childrens properties in the copy.

Add to children properties

That’s correct! Props in React are immutable objects, so onceReact.cloneElement has created a copy of the element it can then add to the childrens properties in the copy.

Extend the functionality of children components

That’s correct! Props in React are immutable objects, so onceReact.cloneElement has created a copy of the element it can then extend the functionality of the children components. 

React children is one of the special props all
your components have implicitly that along with
the react composition model, enables a new paradigm
of component design. So far you have discovered
how to leverage this special prop
in read mode only, meaning that your components consume it as it is provided. But what if I told you that
you can go even further and transform your
children’s elements in any way, shape, or form. To illustrate, see the Little Lemon
restaurant once a way to visualize a summary of live orders as they
come in from customers. What would be really
useful for the chefs working in the
kitchen is to display each customer order in its own separate row with
the name of the dishes, the amount of each
dish, the total price, the time of submission, and the full name
of the customer. Well, by using a set of new react APIs that will enhance your component
design skills, you will be able to
solve this problem for Little Lemon with a smart
and efficient solution. Let’s start by exploring two of these powerful react APIs. React.cloneElement
and react.children. In this video, you’ll learn how to use both of these react APIs and how they can be used to manipulate the Render
Output dynamically. Let’s explore the
first of these APIs, React.cloneElement
in more detail. This is part of the
react top-level API and it’s used to manipulate
and transform elements. Top-level API refers
to the way you would import those functions
from the react package. You can either import react
as a global object and the top of your file and access them as methods
on that object. Or alternatively
as a named import. Recall that elements are just
plain JavaScript objects. The react uses internally to describe what you want
to appear on the screen. React.cloneElement
effectively clones and returns a new copy of
a provided element. The first argument is the react element you
would like to clone, and the second argument is the prompts that
will be added and merged with the original props
passed into the component. Remember that prompts in
react are immutable objects. You must create a
copy of the element first and perform the
transformation in the copy. That’s exactly what
React.cloneElement allows you to achieve. This API is useful to allow a parent to perform the
following operations; modify children
properties, add to children properties and extend the functionality of
children components. For example you could
add another prop dynamically to the
submit button element illustrated before.
Another important top-level API useful for children manipulation
is react.children, which provides utilities
for dealing with the props.children
data structure. The most important method
is the map function. React.children.map
is very similar to the map function from arrays and invokes a function in every child contained
within its children prop, performing a transformation
and returning a new element. Don’t worry if those APIs
still sound a bit confusing. Let’s get into some code to
give you a better picture. The Little Lemon restaurant is busy receiving live orders. To visualize a summary
of those orders, I have been tasked to display
each one of them in a row, having a fixed
horizontal spacing between each piece
of key information. In this application, there
is an order that has been submitted for a client
requesting a pizza margherita. Each order contains the
name of the dish, amount, total price, time of submission, and full name of the client. I have created a row component that will handle the
separation per item. At the moment, it just returns the children
as they are provided. All the items on screen or
cramped with no separation. Let’s go ahead and use both
React.cloneElement and React.children.map as
the implementation to solve the separation problem. The first thing
I’ll do is use the children.map function to
iterate through each child. So far, I am returning
each child as it is, so still no changes
on the screen. To implement even
horizontal spacing. I am going to add some
custom style that will set some left margin in each child
except for the first one. In order to specify
the amount of space, I will create a new
prop called spacing. There will be the number
of pixels and we’ll use string interpolation to set the margin style
properly in pixels. Now that the style is defined, I need to attach it as the
style prop in each element. In the map function callback, I’ll return a new copy of the element using
React.cloneElement. The second argument is what lets you specify the new props. In this case, I’d like to add a new style prop that will
merge the previous style. If the element is
not the first child, then I’ll also merge the child style object that contains the margin
left statement. Great. The last step then is to use the spacing property
in the row component. Let’s set it at 32
pixels. There you go. Each live order now presents
all the information clearly so that chefs don’t make any mistakes and cook
the wrong pizza. In this video, you have
learned about two new APIs, React.cloneElement and
React.children.map. Providing you with a
powerful tool set to manipulate children
dynamically with ease.

Lab: Exercise: Build a Radio Group Component

Instructions

Reading: Solution: Build a Radio Group Component

Reading

Practice Quiz: Self-review: Build a Radio Group Component

In the RadioGroup component, when cloning each child element (RadioOption), what’s the condition that determines the value of the new checked prop that gets merged into the existing props of each RadioOption component? Recall that the RadioGroup component has three props – onChange, selected and children – and that each RadioOption component receives two props – value and children.

Inside the RadioOption component, what should be the value of the onChange prop from the radio input element? Recall that the RadioOption component receives four props – value, checked, onChange and children.

What are the arguments that the React.Children.map function receives?

Video: Spread Attributes

Spread Operator: Simplify React with Power and Caution

This video dives into the spread operator, a powerful tool for creating flexible and efficient React components. Here’s a breakdown:

What it is:

  • Three dots (…) operator that simplifies object manipulation.
  • Used for copying, merging, and forwarding props in React.

Benefits:

  • Simplified code: Reduces boilerplate by spreading existing object properties.
  • Flexible components: Makes components adaptable to different data and props.
  • Clean API: Provides a clear and consistent interface for consumers.

Key points:

  • Object Operations:
    • Copy an object with {...obj}.
    • Merge objects with { ...obj1, ...obj2 }.
  • React Props:
    • Spread props from an object to a component with {...props}.
    • Be mindful of prop order: later props override earlier ones.

Example:

  • Button component: Forwards native button props and adds custom type prop.
  • Login button: Extends Button with pre-configured type and onClick while still spreading props.

Caution:

  • Overriding props with spread may not be intended.
  • Consider prop order to avoid unexpected behavior.

Takeaways:

  • Spread operator is powerful for creating flexible and efficient React components.
  • Be aware of potential pitfalls and use it strategically for clean and predictable code.

This summary condenses the key points of the video, focusing on the benefits and applications of the spread operator in React development, while also highlighting potential pitfalls and best practices for its use.

# Spread Operator in React: Mastering Flexibility and Efficiency

Welcome to this tutorial on the spread operator, a versatile tool that can streamline your React development!

Here’s what we’ll cover:

1. What is the Spread Operator?

  • Syntax and core functionality
  • Object copying and merging

2. Spread Operator in React Props

  • Forwarding props to components
  • Creating adaptable components
  • Maintaining clean APIs

3. Best Practices and Cautions

  • Prop order and overriding
  • Strategic usage for clarity and predictability

4. Hands-On Examples

  • Building a flexible Button component
  • Creating a LoginButton with pre-configured props
  • Troubleshooting common pitfalls

5. Takeaways and Next Steps

  • Key points for effective spread operator usage
  • Further exploration and practice

Ready to dive in? Let’s get started!

  • In a restaurant ordering system, you can use the spread operator to copy and merge objects. For example, if a customer wants to make a last-minute change to their order, you can use the spread operator to create a new object with the updated information.
  • In a shopping cart application, you can use the spread operator to copy and merge objects. For example, when a user adds an item to their cart, you can use the spread operator to create a new object that includes the existing items in the cart as well as the newly added item.
  • In a social media application, you can use the spread operator to pass props to different components. For example, when rendering a post, you can use the spread operator to pass all the necessary props to the post component, such as the post content, author information, and comments.

The spread operator is one of the coolest
additions to the JavaScript language. Thanks to the spread operator,
which is represented by three dots. Common operations that previously required
a bit more code like cloning an object or array are now so much simpler. So in this video you will learn how to
use the spread operator and objects, how to spread native
properties to DOM components. How to design flexible components and about the caveats when
using the spread operator. Imagine that the little lemon restaurant
wants to have a simple welcome screen where users can sign up or log in depending on whether
they have an account or not. The sign up and log in buttons are in
nature very similar with differences in the text and
the action taken when they’re clicked. To achieve this implementation,
you could define a button component that encapsulates the native
HTML button element and uses the same props as
its native counterpart. However, a button presents dozens of
different properties for customization. Instead of having to specify each
of them manually, the spread operator can be used to forward all of
them without typing each one manually. React embraces this operator at
its core when it comes to props. But before digging deeper, let’s
refresh with this operator enables for objects in pure JavaScript. The spread operator can be applied to
different data types in JavaScript such as arrays, objects and even strings. Since react props are just objects, this lesson is going to be focused
strictly on the object type. Copying and merging objects are the two
main operations you may perform with these operators. For a simple copy of an object, this
is the syntax required curly braces and the three dots preceding
the object to copy. In this example, order amend represents
a last minute change to the type of pizza ordered by the customer. For merging first you need to spread the
properties from the original object and then provide the new properties to be
added or to replace original properties. The property called item has been
replaced with the new order information. Great, now that
the preliminaries are covered, let’s explore how react
uses the spread operator. This order list component example
renders an order component. Each order component expects four props
an ID, user name, item and price. This first example shows how
you might usually do it, passing all the props in
the return statement explicitly. However, this can be simplified if
you already have the props your order component needs in an object. Here, you can see that only the spread
operator is required in the return statement, saving us time by
just spreading all the props and avoiding having to type them manually. This pattern allows you to
create flexible components but there are also some caveats you need
to keep in mind when using the syntax. Let’s explore this in more detail
with an example demonstration. In this application,
I have created a simple welcome screen for little lemon restaurant where
users are able to sign up or log in depending on whether
they have an account or not. At the top, I have to find a button component that
wraps the native button from the DOM. This component expects the same
props as its native counterpart with the addition of the type prop, which is a
custom prop that determines the background of the button based on the theme provided. Here is a clear example of using
the spread operator to group all the props that belong to the native button and
explicitly extract the custom props I have defined for this component and
our react specific, type and Children. This implementation is clean for developers since they can provide all
the props a native button would expect. The second example is a login button
component that renders the custom button component I have created itself. This login button does
some pre-configuration by fixating some of the props from the button
component in this case type and on click while still passing the native button
props down with the spread operator. Now the app component renders the two
buttons and uses the button component for the sign up and
the login button component for login. The buttons are both configured here
to send the user to the sign up page, unless they have an account in which case
the login button components original on click function will send
them to the login page. I have also provided both with an on
click handler to show an alert about the intended action
when the button is pressed. However, observe how I have mistakenly
provided the same alert message that is used for
sign up on the login button component. Hence, overriding the on click handler
that the login button already defines. Now, can you guess what the message of
the alert will be when I click on it, I’ll give you a few
seconds to think about it. Well, if you guessed logging in,
you guessed right. The reason is that, even though I have overridden the on click
prop in the log in button component, its implementation is done in a way that
prevents that overriding from happening. Why is that because of the order
of the spread operator? If I go ahead and spread the props at
the end instead right after on click. The behavior is different and
signing up is output instead. So what are the main
takeaways from this lesson? The spread operator is a great tool that
enables the creation of more flexible components, especially when forwarding
props automatically to other components that expect them as well as providing
your consumers with a nice component. API. However, keep in mind that depending on the order of the spread, the behavior
may differ so you need to be conscious about your decision when it
comes to component design. In the example of the login button before
it may make sense to prevent the override of the on click property but it may not
be the intended case for other props. Well done. I hope you’re getting an idea of the
multiple benefits that can be gained from using these react tools.

Practice Quiz: Knowledge check: JSX

Let’s suppose you have the below JSX that gets returned from a component, what would be the equivalent object representation (Element) that React will create internally?

What is the concept of component specialization?

You would like to clone a React element by using the React.cloneElement API, where the particular element has the below structure:

Imagine you are using the spread operator in the below component as follows:

Amongst the below expressions, select all that will not render anything on the screen when being used in JSX.

Reading: Additional resources

Reading

Reusing behavior


Video: Cross-cutting concerns in React

Summary of the video on cross-cutting concerns in React:

  • What are cross-cutting concerns? Generic functionalities needed in many places, like managing permissions, handling errors, or logging, not directly related to app’s core logic.
  • Components, not always ideal for reusability: Components are the main unit of reuse, but repeating cross-cutting logic leads to redundancy and complexity.
  • Subscription example: Live order and newsletter list components share similar data subscription and update patterns.
  • Higher-Order Components (HOCs): A function that takes a component and returns a new one with enhanced capabilities. Perfect for encapsulating cross-cutting logic without modifying original components.
  • HOC example: withSubscription HOC takes any component and adds live data subscription with configurable data source (orders or users).
  • Benefits of HOCs: Reuse code, keep components stateless, centralize logic, and improve maintainability.
  • Bonus: Briefly mentioned another pattern called Render Props for cross-cutting concerns.

Key takeaways:

  • Cross-cutting concerns need efficient reuse strategies beyond components.
  • HOCs offer a powerful way to encapsulate and share common logic for different components.
  • Using patterns like HOCs leads to cleaner, more maintainable, and reusable React applications.

Tutorial: Handling Cross-Cutting Concerns in React

Welcome to this tutorial on managing cross-cutting concerns in React applications! Cross-cutting concerns are functionalities found across multiple components, like authentication, logging, or error handling. Repeating this logic leads to code duplication and reduces maintainability. This tutorial will explore best practices and patterns for tackling these concerns effectively.

1. Identifying Cross-Cutting Concerns:

  • Look for repetitive functionality: Analyze your codebase for logic used in multiple components that isn’t directly related to their specific features.
  • Think beyond components: Consider concerns like authorization, data fetching, or state management that span various components.
  • Common examples: Authentication, authorization, logging, error handling, data fetching, state management, theming, accessibility.

2. Strategies for Managing Concerns:

  • Component Composition: Leverage props and children to pass required functionality down the component tree. Though simple, can become cumbersome for complex concerns.
  • Render Props: Pass a function as a prop that renders child components, centralizing the cross-cutting logic. Offers more flexibility and separation of concerns.
  • Higher-Order Components (HOCs): Wrap existing components with a function that injects additional functionality and props. Encapsulates logic efficiently and avoids modifying original components.

3. Implementing a Cross-Cutting Concern with HOCs:

Let’s build an HOC for data fetching and state management:

a) Define the HOC:

JavaScript

const withData = (WrappedComponent, fetchData) => {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    fetchData().then(setData).finally(() => setIsLoading(false));
  }, []);

  return (props) => (
    <WrappedComponent
      {...props}
      data={data}
      isLoading={isLoading}
    />
  );
};
  • WrappedComponent: The component to be enhanced with data fetching.
  • fetchData: Function that retrieves data for the wrapped component.
  • data & isLoading: State variables holding fetched data and loading status.
  • useEffect: Fetches data on mount and sets state.
  • Returns: A function that renders the wrapped component with additional props: data and isLoading.

b) Example Usage:

JavaScript

const ProductList = (props) => {
  const { data, isLoading } = props;

  if (isLoading) {
    return <p>Loading...</p>;
  }

  return (
    <ul>
      {data.map((product) => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
};

const EnhancedProductList = withData(ProductList, async () => {
  // Fetch product data from API
});

<EnhancedProductList />;
  • ProductList: Component displaying the product list.
  • EnhancedProductList: ProductList wrapped with the withData HOC.
  • Data and isLoading props injected from the HOC.

4. Benefits of Using HOCs:

  • Code reusability: Encapsulate logic once and use it across multiple components.
  • Component separation: Keeps components lean and focused on their specific UI.
  • Improved maintainability: Makes cross-cutting logic easier to understand and modify.
  • Testability: Simplifies testing of common functionalities.

5. Further Exploration:

  • Context API: Provides a mechanism for global state management, useful for certain cross-cutting concerns.
  • Redux: Popular state management library for complex applications with extensive cross-cutting logic.
  • Libraries & Frameworks: Many libraries and frameworks offer solutions for specific cross-cutting concerns, like authentication or data fetching.

Remember, choosing the right approach depends on the specific concerns and complexity of your application. Experiment with different strategies and find the one that best suits your needs!

Bonus: Keep in mind that using too many HOCs can add complexity and lead to nesting hell. Aim for balance and clarity when structuring your code.

A higher order component (HOC), is an advanced pattern that emerges from React’s compositional nature. 

What are some of the benefits of using a HOC in your solution? 

  • It enhances or extends the capabilities of the component provided.
  • You can define logic in a single place, share it across many components, and keep them unchanged and stateless.

That’s correct. A HOC transforms a component into another component. In other words, it enhances or extends the capabilities of the component provided.

When building React
applications, you will find yourself creating some generic
functionality that is not related to the applications
business logic and that is needed
in many places. For example, think about managing different
permission roles, handling errors,
or even logging. They are all required
for any application, but are not necessary from
the business point of view. This group of functionality
is what falls into the category of
cross-cutting concerns. In this video you are
going to learn about cross-cutting concerns and
why components despite being the primary
unit of code reuse in React aren’t always a good
choice for this kind of logic. You will also discover why new patterns were introduced
to solve this problem. Excited to learn more, well, let’s get started. Imagine that you are tasked with building the
logic to display a list of live orders for the little lemon restaurant app. Let’s explore how this
could be achieved. Here is a valid
implementation for a live orders list where local
state is used for storing the current list
of orders and use effect handles both the
subscription and on subscription to the
live data updating the order’s value as soon
as a new order arrives. Now, imagine the little lemon also needs a place in
the application to keep track of the
number of users subscribing to its
newsletter in real-time. This could be a
valid implementation for such functionality. Can you identify
any similarities between live orders list
and newsletter list? They are definitely not
identical since they call different methods on data source and render a different output, but much of the
implementation is the same. Upon examination, they both add a change listener to
data source on mount, set new state whenever
the data source changes and remove the
change listener on unmount. You can imagine that in a large app the same
pattern of subscribing to data source and setting
local state with new data will occur
over and over again. So far you have seen that our custom hook to
encapsulate that logic is one of the solutions at your disposal, however, that introduces the issue of having to alter the
implementation of each component that
needs that data and thus making all
of them stateful. How could you define
the subscription logic in a single place? Share it across
many components and keep them unchanged
and stateless. Well, this is where higher-order components
are a perfect solution. A higher-order component
also known as a HOC is an advanced pattern that emerges from React’s
compositional nature. Specifically, a
higher-order component is a function that takes a component and returns
a new component. Whereas a component
transforms props into UI, a higher-order
components transforms a component into
another component. In other words, it enhances or extends the capabilities
of the component provided. Let’s go ahead and examine
how the implementation of this reusable
subscription logic would look with a
higher-order component. With subscription is the
higher-order component that takes the raft component
you would like to enhance with subscription
capabilities as well as a selectData function
to determine the type of data you are getting
from the data source. In this case, either
orders or users. With subscription then returns a new component that renders the provided component
and supplies a new prop to it called
data that will contain the most recent list of items from the data
source of interest. It also passes other prompts through to
the rapt component, which is a convention in HOCs. That’s the implementation, but how about its usage? In this case you would define two different components configured with
custom parameters, one for live orders
and another for newsletter subscribers
all without having to repeat the subscription
implementation in either live orders and user list making this a much
more efficient solution. There’s still one
more pattern for cross-cutting concerns
that you will learn about soon called
render prompts. Great. In this video, you have learned about
cross-cutting concerns and why components are not always
enough for reusing behavior. You also explored one alternative
pattern to encapsulate common behavior in
React applications which are higher-order
components.

Reading: Higher-order components

Reading

Video: Create a HOC for cursor position

Summary:

  • Little Lemon restaurant wants to track visitor behavior on their pizza section to understand which pizzas are popular.
  • They plan to track mouse position to see which pictures capture attention.
  • The video demonstrates using a Higher-Order Component (HOC) to encapsulate the mouse tracking logic.
  • The HOC provides mouse position data to other components through props.
  • Two example components, panel and point trackers, display the data differently.
  • This tracking helped Little Lemon identify a blurry pizza photo affecting sales, which they promptly replaced.

Key takeaways:

  • HOCs can improve code reusability by encapsulating cross-cutting concerns like mouse tracking.
  • React components can receive and utilize data through props.
  • Tracking user behavior can provide valuable insights for website optimization.
When defining a HOC, such as withMousePosition, why is the with part of the HOC name a general convention recommended by React?

It expresses the enhancing nature of the technique.

That’s correct! The with part of the HOC name is a general convention recommended by React, as it expresses the enhancing nature of the technique, like providing a component ‘with’ something else.

The Little Lemon
restaurant is receiving a spike and visits
to their website during the last month due
to customers loving some of the special pizzas the chef
presented to the public. Despite the success,
there are some pizzas that aren’t receiving the
same level of attention, so they have decided
to implement some basic analytics to better understand which are
the bestsellers and which ones are not being
ordered so regularly. For that, they would like
to track the mouse position of the visitors when they
are in the pizza section, so that they know exactly
which pictures are capturing people’s attention and which ones are overlooked. In this video, I’m going to
show you how to implement such functionality by using a higher-order
components or HOC, which will be in charge of
encapsulating the logic and state to track the cursor
position of the visitors. Then I’ll showcase two
different presentation or components that will consume that data and present
it in different ways. Are you ready? Let’s begin. The little application has been created with Create React app, so far in the rendering
part of the app component, there is a header
displaying the title of the restaurant and
two components, panel most logger and
point mouse logger. They both expect a mouse
position prop and will return null if that
prop is not provided. That’s why at the moment they don’t render anything at all. You could implement the
mouse tracking logic in each component but
recall that it would incur code repetition
and duplication of the same logic in
two different places. That’s why the
recommended approach is to use one of
the techniques that React provides for encapsulating
cross-cutting concerns. In this example, I will illustrate how to do
this with an HOC. I call this HOC with
mouse position. The width part of the name is a general convention
recommended by React since it expresses the enhancing nature
of the technique, like providing a component
with something else. Recall that an HOC is
essentially a function that takes a component and
returns a new component. Let’s complete the
initial scaffold and return a component
that will render the wrapped component
provided to the function without forgetting to spread
the props it receives, so that they will pass-through. Great. Now to track the
position of the cursor, I would need to define a
new piece of local state, which I’ll call
mouse position for the data and set mouse
position for the state setter. The initial state will be an
object with two properties, x and y to define the two-dimensional
coordinates on the screen and I will
set both to zero. X equals 0 and y equals 0, represents the top-left
corner of the screen. Next, I would need to
set a global listener in the window object for
the mouse move events. Since this is a side-effect, I need to perform
the subscription and unsubscription logic
inside use effects. Let’s go ahead and do that, I will add a new
event listener for a mouse movement to
the window object. For the call back, I will name the function
handleMousePositionChange. That for now,
doesn’t do anything. It’s important to remove any subscription when
your component unmounts. The way to do that is by
returning a function from use effect and then performing
any cleanup needed. In this case, I would
have to use the window.removeEventListener
passing as arguments, the mouse move event and the same callback
function as before. To complete the logic and set the state with current
mouse position, I need to read that information from the browser event object, which is passed as an
argument to the callback. That event object contains two properties that
define the coordinates, clients X and client Y. I will assign both of them to the
corresponding dimension. Finally, the last
step to complete the implementation is to
set a new prop called mouse position in the
rapt component to pass that information down to all components that are
interested in that data. Great. Now, that
the implementation of the HOC is finished, let’s add the last few pieces to display the mouse
position on the screen. To enhance the two components
previously defined panel mouse logger and
point mouse logger, I will use the HOC to create two new component versions
that will be aware of the mouse position data
and I’ll call them panel mouse tracker and point
mouse tracker respectively. Finally, I will use the enhanced versions in the rendering part of
the app component. Amazing. The requirements
are now finalized. If I move the cursor
around the screen, you can see two
different trackers that display the same information
in different ways. One as a panel and the one
below as a data point. Well, that’s the
end of this video. Little Lemon restaurant now uses this solution to
track their pizza loving customers and have
discovered that something was affecting the sales of
their pizza de Avila. Guess what? After an employee investigated that particular
pizza on the app, they noticed that one of the
photos was a bit blurry, thanks to this little
tracking application, they have now taken action and uploaded new
high-quality photos. The next time a customer
is exploring the menu, they won’t miss the
pizza de Avila.

Video: Render props

The video presents the render props pattern as an alternative to higher-order components for code reusability in React. It uses the analogy of choosing the right utensil for different foods to explain how different techniques are best suited for certain situations.

Here are the key takeaways:

  • Render props pattern: A component takes a function called “render” and calls it in its own render logic. This function receives arguments (often data) and returns a React element to be displayed.
  • Benefits:
    • Encapsulates common logic like data fetching.
    • Keeps components independent and easy to maintain.
    • Provides flexibility in how data is presented.
  • Application example:
    • Little Lemon Restaurant wants to display the number of desserts and drinks available.
    • A dataFetcher component fetches data based on URL and sends it via the render function.
    • Separate components display the dessert and drink counts using the received data.
  • Comparison to higher-order components:
    • Both enhance components without modifying their original implementation.
    • Render props injects props dynamically through the render function, while HOCs inject props directly.

Overall, the render props pattern is a powerful tool for reusing code and promoting flexibility in React development.

What is the result of the return statement of the DataFetcher component?

The component returns the result of calling the render function.

That’s correct! The DataFetcher component returns the result of calling the render function and has no other rendering business.

So far you have learned about a technique
called higher order components that is used to encapsulate common functionality,
but it’s not the only one available to you. For example, you can choose between
different eating utensils depending on the type of food you’re eating. Some chopsticks for your favorite sushi
dish or a fork for a delicious carbonara. But there’s nothing wrong with using
a fork for eating sushi after all. Not everyone has learned
how to use chopsticks and it’s the tool that makes
the job easier that matters. Well, this is also the case when
it comes to code reusability. There are several tools you can use to
share code between react components, and in this video you are going to
be introduced to a new one, the render props pattern. Say the Little Lemon Restaurant
is looking for a way to keep count of all
the items it has on the menu. They would like to display this
information in the application so they know when they need to replenish
stock and to make it easier for customers to see what is or
isn’t available at any given time. That information is stored on a server. So we would have to be fetched
first prior to displaying it. There are various ways to define
the fetching logic like a higher order component. However, render props is also a powerful
technique you can leverage to reuse common code. The render props technique is so appropriately named that it’s
almost self explanatory. It’s about using a prop called render
with a particular attribute that it has to be a function. To be more precise, a component with a
render prop takes a function that returns a react element and calls that
function inside its render logic. For example a meal provider component
could use this pattern if you remember a higher order component
enhanced a component by providing new props into it with render props. However the new props are injected
dynamically as the parameter of the function. You may already have recognized
some similarities between the two. The end goal is the same to enhance
components without modifying their original implementation. The way in which they
inject those new props or enhancements is what differs to
better illustrate this point. Let’s explore an application that
showcases the implementation of a component that uses
a render prop in this example the little lemon restaurant would like
to keep account of all the desserts and drinks that it has in the menu. That information will need to be fetched
from a server that they control and displayed in the application
with a single piece of text. The logic for fetching data is one
example of a cross cutting concern. Multiple components may depend on
data that lives somewhere else but you don’t want to implement
the same fetching logic over and over in every component that needs it. Right this is a good place to use
the render props pattern to abstract this functionality to
showcase how it works. I have created a component called
data fetcher whose only purpose is to fetch data based on a U. R.
L. This is one of its props but it’s the second one that should catch your
attention and that’s the render prop. I’m not fetching real data in this
example but I have created a mock if else statement that will return
either a list of all desserts or drinks available based on the U. R. L. Path as usual. This fetching logic is a side effect
that should be placed inside use effect. Finally let’s move to
the return statement. This is the unusual part. The component is returning the result
of calling the render function and has no other rendering business. This is what makes it very flexible. Data fetcher only has one
purpose fetching data and the way they receive it is via the
argument in the render function which is the local state used to store
the list of desserts or drinks. It’s then up to the developers
to decide how they would like to present that data on the screen. Finally, let’s explore the two
presentational components. I have defined to show the number of
desserts and drinks available in the menu. The desserts count component uses a
particular endpoint to fetch desserts and uses a paragraph element
as the render prop, displaying the number of
desserts as a single text. The same applies to the drinks count
component with the difference being that he utilizes another U. R.
L. And instead shows a header element
reflecting the number of drinks. Finally, the app component
renders both of them, and the results
are displayed on the screen. You have learned about another technique
you can use in addition to higher order components, which is
the render props pattern. Hopefully, now that little lemon
keeps a live count of drinks, they can replenish their fridge
with your favorite refreshments.

Lab: Exercise: Implementing scroller position with render props

Reading

App.js

Reading: Solution: Implementing scroller position with render props

Reading

Practice Quiz: Self-review: Implementing scroller position with render props

Considering the MousePosition component receives a prop called render, which is a function, what are valid options of JSX returned from the component?

The PointMouseLogger component returns the below JSX.

The App component initially presents the below output structure

Practice Quiz: Knowledge check: Reusing behavior

When dealing with cross-cutting data in your React applications, what are some of the problems of using a custom hook to encapsulate that logic? Select all that apply.

Here, you can find the APIs of some higher-order components that have been already implemented. Amongst all the options, which ones present an invalid signature that doesn’t follow the convention? Select all that apply.

What are some of the best practices to follow when implementing the higher-order component pattern? Select all that apply.

What are some of the differences between higher-order components and render props? Select all that apply.

True or false. A component with a render prop as renderer can do anything a higher-order component can do.

Reading: Additional resources

Reading

Integration tests with React Testing Library


Video: Why React Testing Library

This video explains the importance of automated testing for React components and how to achieve it using Jest and React Testing Library.

Key points:

  • Why testing is important:
    • Ensures app functionality before delivery.
    • Reduces user complaints and saves time/money.
  • Testing best practices:
    • Avoid implementation details of components.
    • Tests should mimic user interactions.
    • Maintainable in the long term.
  • Tools:
    • Jest: JavaScript test runner with mocking capabilities.
    • React Testing Library: Set of utilities for testing React components without relying on implementation details.
  • Example test:
    • Verifies presence of a link to Little Lemon’s webpage.
    • Demonstrates using Jest and React Testing Library functions.

Additional notes:

  • The video mentions additional resources for learning more about mocking.
  • Future videos will cover writing more complex tests.

Which of the following statements are true about Jest and React Testing Library tool? Select all that apply.

React Testing Library is a set of utilities that let you test React components without relying on their implementation details. 

That’s correct! React Testing Library is designed to fulfill all testing best practices out of the box, so that you are able to focus on the business logic your tests need to run assertions on.

Jest is a JavaScript test runner that lets you access an artificial DOM,which provides an approximation of how the browser works.

That’s correct! Jest is a JavaScript test runner that lets you access an artificial DOM called jsdom. While jsdom is only an approximation of how the browser works, it is often good enough for testing React components.

As the developer for Little
Lemon Restaurant application, how could you guarantee that the app you created
works as intended? Well, you may choose to rely on your
methodical ability to manually interact with
all the different parts of the application yourself, ensuring the app is
fully functional. However, manually testing every new incremental
change you’d like to make is
likely to be tedious, error-prone, and time-consuming, especially as your app
grows in complexity. That’s where automation
tests come in. In this video, you
will learn how to write tests properly for
your React components. You will achieve this by exploring why testing
is important, and best practices
when creating tests. Being introduced to
the tools Jest and React Testing Library for
structuring your tests. As well as working through
a practical example of testing a component
using these tools. Just like factories
perform testing of the products they build to ensure that they
work as expected, developers need to do the
same with their code. A well-designed suite of automation tests is
particularly effective in allowing you to
discover defects or bugs before delivery
to the client. In doing so, testing
is important for guaranteeing the quality of
the software you develop. Further, by catching bugs before they find their way into
a live application, testing reduces the number
of user complaints, and can ultimately save an
organization time and money. Now that you have an idea of
why testing is important, what are the best
practices you need to keep in mind when
writing your tests? The first is that your
tests need to avoid including implementation
details of your components. React is just a tool, and your final users will have no notion that React
exists at all. Rather than dealing
with instances of rendered React components, your tests should work
with actual DOM nodes. Secondly, the more you test resemble the way your
software is used, the more confidence
they can give you. Finally, you also want your tests to be maintainable
in the long term. As long as you’re not
changing functionality, any changes in the implementation
of the component won’t break your tests and slow
you and your team down. Now, let’s explore
the two tools that React endorses to
structure your tests, Jest and the React
Testing Library. Jest is a JavaScript
test runner that lets you access an artificial
DOM called JSDOM. While JSDOM is only
an approximation of how the browser works, it is often good enough for
testing React components. Jest provides a good
iteration speed combined with powerful
features like mocking modules, so you can have more control
over how the code executes. Recall that mocking refers to something made as an imitation, and enables you to replace
complex functions from your code with others that are simpler and simulate
the same behavior. Mocking features
can be used to make sure that your unit
testing is standalone. If you’d like to revisit the concept of mocking
in greater depth, you can check out the
additional resources at the end of this lesson. The second tool is
React Testing Library, which is a set of utilities
that let you test React components without relying on their implementation details. React Testing Library
has been designed to fulfill all the best
practices highlighted before, so that you get a
well-configured testing environment
out of the box, and are able to focus on the business logic your tests
need to run assertions on. With the theory covered, let’s go ahead and
implement a test from scratch using Jest and
React Testing Library. When you start a new project
with Create React app, you already get
both Jest and React testing library
pre-installed by default. Plus both tools are
already pre-configured, and there’s an
example test file in your root folder
called app.test.js. Imagine that Little Lemon
has made an agreement with a popular restaurant
aggregator to have its webpage included as a
new URL in its listing. In the app.js file, the app component
renders a link in the page that points to
Little Lemon’s webpage. Let’s go through the
test I created to automatically verify that
the link is always present. The first thing I need
to do is to import both render and screen from the
React Testing Library. The render function is used
to render the component you would like to test and
perform assertions against. Because querying the entire document.body is very common, React Testing Library also
exports a screen object, which is a reference
to that object, and has every query
prebound to it, meaning that it will
automatically ask the whole document
when running a search. Now, to wrap the test scenario, just provides the
global test function, which takes a text description
as the first argument, and a function to
compose all the steps your test needs to go through
as a second argument. This function does not
need to be imported since Jest injects it automatically
in all your test files. The first step is to render the app component in the
artificial DOM environment. Secondly, I used the
screen object to create a query against
the document.body. In this case, I am using the getByText utility
to ask the body tag of the document if it can
find an element inside with a string called
Little Lemon Restaurant, and store the result of that finding in the link
element object. If the search is successful, getByText will return
the found element. Otherwise, it will return null. Finally, to complete the test, I perform an assertion
asking whether the link element from the query above is present
in the document, meaning whether it’s currently
visible on the screen. For that, the global
expect function is used. This is another utility
that Jest incorporates globally without the need
for an explicit import. The expect function
receives the result of a query and appends
the specific matcher. In this example, the
matcher refers to an element visible in
the whole document. If I run the test, it fails. Let’s check the output logs to try to understand
what has gone wrong. It states that it
was unable to find an element with a text,
Little Lemon Restaurant. Interesting. Let’s go ahead and check the app.js
component again. I had made a mistake and typed
orange instead of lemon, something that the test
was able to catch. That’s exactly where you want to see when a failure occurs. Also, you might have noticed how straightforward it is to
write your test assertions. Everything you see in code
translates nicely to how a real user would interact with your app and responds with the behavior that
you would expect. Let’s run the test again now
that the issue is fixed. Great. The test passes and Little Lemon’s online exposure is about to grow even more. In addition to the importance of testing and testing
best practices, you have now learned how to
test your React components using Jest and the
React Test Library. Stay tuned, because soon
you will discover how easy it is to write
more complex tests.

Video: Writing the first test for your form

  1. Issue: The restaurant received negative reviews without specific feedback, making it challenging to address the problems.
  2. Solution: To improve, they made the text box mandatory when users rate below five (on a scale of ten). This ensures additional comments are provided.
  3. Automated Tests: They added automated tests to catch errors caused by faulty updates.
  4. Feedback Form: The application includes a feedback form with a numerical score input (0-10) and a text box for comments.
  5. Submit Button Logic:
    • If the score is below five, the submit button is disabled.
    • Users must add a comment of at least ten characters.
  6. Code Details:
    • The entry point is the app.js component.
    • The feedback form component receives a prop function for submission.
    • It manages local state for the input fields.
    • The button disabled logic depends on the score and comment length.
    • The handleSubmit function triggers the parent’s submission function.

In summary, The Little Lemon Restaurant implemented changes to gather more meaningful feedback and ensure quality through automated testing. 🍋👍

When writing a part of your test to locate the range input and fill it with a value, which functions do you need to use? 

fireEvent.change()

That’s correct. To fill the input and update the state with a value, you can use the fireEvent.change() utility from React Testing Library.

screen.getByLabelText

That’s correct. Screen.getByLabelText asks the root document to find a label tag whose text contains a specified text value and then return the input element associated with that label.

Imagine that The Little Lemon Restaurant
started receiving a few bad reviews from its customers. The problem is that they could not figure
out what was wrong and act accordingly. Since users only provided a low
numerical score, skipping the part of providing additional feedback and
passing that information to the chefs. In order to solve that, they’ve decided
to make the common text box mandatory as long as the score provided by their users
is lower than five in a scale to ten. Additionally, they would like to shield
this new logic with automated tests so whenever any changes are performed,
the test suite would run and be able to catch any potential
errors incurred by a faulty update. So the application consists of a feedback
form that contains a range input for a numerical score ranging
from zero to ten and a text box to incorporate
additional comments. To satisfy the requirements
desired by Little Lemon, the submit button will be disabled
if the score is lower than five, forcing users to add a comment
of at least ten characters. Now let’s examine the code. The entry point is the app dot JS
component where I’m rendering a feedback form component. This component receives a prop on
submit which is a function that contains the values of
the form as parameters so that the parent app component
can perform the submission. The feedback form represents an HTML
form and includes two controlled components via local state,
arranged input, and the text area. There are two pieces to
highlight in this component. The first is the button disabled logic is
disabled is the variable that controls that state and is set to true if
the score is lower than five and the comment has less than ten characters. The other important piece is the handle
submit function which is hooked into the form on submit attribute. When the submit button is clicked,
the handle submit function will be called. This function itself calls the prop
function provided by the parent with the corresponding form values. Well, it’s clear that the feedback form
component contains all the business logic of interest. So let’s go ahead and write a test for
the submission logic. The convention for test is to create them inside a file
that has the dot test extension. That way, jest the test runner is able to
pick them up automatically when you run the test command in your terminal. As I have already written a test scenario,
I will now walk you through each line of code so that you understand how
the test is structured step by step. The test scenario is checking that users
are prevented from submitting the form right away if the score
is lower than five and there is either no additional feedback or
it’s too short. First, I create a new
mock function with jest, recall that a mock function is a special
function that allows you to track how a particular function
is called by external code. When the feedback form calls the function
you provide as the on-submit prop, you will be able to explore
the argument passed in the call. Then, I render the feedback form and pass
the mock function as the on-submit prop. The following steps are needed to locate
the range input and fill it with a value, notice that to find the input I’m
using the screen.get by label text and passing a regular expression
to match against. Screen is a utility object from
react testing library that represents the whole page which
basically translates to asking the root document to find a label tag whose
text contains the word score and then return the input element
associated with that label. To fill the input with the value you have
to use the fire event utility from React testing library and
call the change function. While React-controlled components update
their state via the unchanged prop, React testing library follows
a slightly different convention, removing the on part and
having the update method as lower case. To simulate the form, submission I
have to locate the button element, observe how I’m using
a different query method. Get by roll which looks at elements
with a specific role attribute. This will work well since the HTML button
already has the button role internally set, to simulate the event I
need to provide two arguments. First, the input element in question and second the browser event object which
holds the new value as target.value. To perform a button click I
have to use fireevent.click. It follows the same convention as before
removing the on-site of the prop and having everything in lower case. Great. The final two statements
are the assertions of the test. The first one illustrates an example
of an expect matter that wants to check the opposite by pre-pending the not
before calling the final matter. What it’s asserting is that the function
that handles the submission of the form has not been called, which is what I’m expecting when
an additional comment has been omitted. Furthermore, I have added the second
assertion to make sure the submit button is indeed disabled by using
the to have attributes matter. And that’s it. Well, done for
reaching the end of this demonstration. In this video, you learned how you can
shield your business logic with a few lines of powerful code,
thanks to the React testing library. And what’s more important
it has enabled the chef at Little Lemon to finally receive
the necessary feedback and make sure all the new pizzas have
a bit more extra cheese on top.

Lab: Exercise: Writing more test scenarios

Reading

Code

Reading: Solution: Writing more test scenarios

Reading

Practice Quiz: Self-review: Writing more test scenarios

What’s the correct call to fire an onChange event on an input with react-testing-library’s fireEvent API?

How would you fire a click event on a submit button with react-testing-library fireEvent API?

When locating an element by using one of the screen querying methods from react-testing-library, such as screen.getByRole or screen.getByLabelText, what would be the return value of the call if the element is not found?

Reading: Introduction to continuous integration

Reading

Video: Style guides

Murtadha, a software engineer at Meta, shares his passion for style guides and why he believes they are important. Here are the key takeaways:

Why follow style guides?

  • Improved Code Readability: Consistent formatting makes code easier to understand for everyone, including future developers working on the codebase.
  • Reduced Burden: Proper naming and structure can make code self-documenting, reducing the need for additional comments and documentation.
  • Easier Debugging and Maintenance: Clear and consistent code is easier to troubleshoot and fix problems in.
  • Team Harmony: Shared style guides ensure everyone works on the same page, reducing confusion and inconsistencies.

Benefits for Engineers:

  • Invest in the Future: Learning style guides early saves time and effort in the long run.
  • More Maintainable Code: Well-formatted code improves the long-term health and stability of applications.
  • Efficiency: Reduced need for comments and documentation leads to faster development.

Overall:

Style guides may seem trivial, but they play a crucial role in creating clean, understandable, and maintainable code. This benefits both individual developers and the overall project health.

So I am passionate about style guides. I actually used to be really bad and
really used to dislike them and think like they’re not important. But now,
if I see something that’s out of style, I like really notice it and it’s like,
it’s so, to me it’s very frustrating. So now I, I take them seriously. My name is Murtadha. I’m a software engineer at Meta
based in the Seattle office. So a lot of the times people think
style guides are silly or useless, and they may not actually
give them a lot of value. I see this with a lot of new developers
when I’m reviewing their code. A lot of my comments
are actually about styling, and it may seem like I’m being annoying or I’m
being nitpicky about unimportant things. Because following style doesn’t
functionally change the way code works. It just changes the way the code looks. And so, people are like, well why does it
matter, this still does the same thing,? But it matters because it makes
code much easier to read. It makes code much easier to debug and
work with. And this is a big deal, because a lot
of times when we’re writing code, we’re not just writing it for ourselves,
we’re writing it for other people. So paying it upfront and taking the time to style your code
correctly is really worth it. One of the things we look for in
the following style guides is to make sure that code is self documenting,
and that really helps. So that developers are not taking the time
to write comments and being elaborate and explaining things. Where if you look at the code,
you can understand it and read it and it documents itself just by the way
that variables are named or by the way, functions are structured. And that’s really important because it
removes the burden from the developer to write documentation and it also removes the burden from other
developers to read the documentation. It also makes it easier to fix problems. When somebody new was looking at the code
and a lot of times we write code and then we don’t keep writing or improving or
maintaining it, somebody else comes. And so, it’s a service to
the people that come after us, that we write code in a clean,
well styled way. So that when they look at it, they’re
actually able to understand it easily. At Meta, we have a team or a bunch
of teams that are kind of the owners of setting the style guides to make
sure the company is following similar or consistent guides across
the different code bases. Because style guides are one of those
things that could involve different opinions and tastes, and
different ways to achieve the same thing. We want to be consistent, even if there’s
multiple ways to do the right thing. We want to choose one way and stay consistent across our our code
base just so that developers are not confused when they look from one
part of the code base to another. Everyone at Meta is using or following
the style guides that are created and managed by the teams responsible for them. So I’m a engineer developer and I am daily
following and using these style guides, just like everybody else in
the company who’s writing code. Learning about coding and style guides,
it may seem like why do I need this? And it’s actually not that complicated. You need it because it’s
like an investment. Following these style guides and
and adhering to them and learning the good style guides will make
a big difference in the application and its stability, usability, readability. As well as anything that you do
in the future to improve it, whether you’re adding new features or
you’re fixing a bug. So it may seem like it’s the unimportant
part of developing and writing software, but it actually makes a big difference if
you’re writing code for the long term.

Practice Quiz: Knowledge check: Automated testing

Why is automated testing important? Select all that apply.

What are some of the best practices when writing your automated tests? Select all that apply

Imagine you have a component that renders both an input tag and a label tag with the exact text Comments:. Inside your test, you have the below piece of code:

In a particular test that’s been written for a form component, you encounter the below two lines of code. What kind of data would the handleSubmit variable represent?

What are some of the benefits of Continuous Integration (CI)? Select all that apply.

Video: Module summary: JSX and Testing

React JSX Advanced Patterns and Testing: Key Takeaways

Review of Key Concepts:

  • JSX: Components (functions with props) return element trees, elements represent DOM.
  • Component Composition: Containment (children prop) and Specialization (special cases).
  • Dynamic Children Manipulation: React.cloneElement and React.Children.map.
  • Spread Operator: Copying/merging objects, spreading props efficiently.
  • Advanced Patterns:
    • Cross-Cutting Concerns: Not business logic, needed in many places (e.g., data fetching).
    • Higher-Order Components: Functions that create new components (e.g., for data fetching).
    • Render Props: Special prop with a function returning JSX (alternative to HOCs).
  • Testing with React Testing Library:
    • Importance of tests, best practices, using jest as test runner.
    • Basic test structure and practical examples.
    • APIs like screen for querying, expectations and assertions.

Congratulations! You’ve mastered advanced React JSX patterns and testing. Now go build amazing applications!

Well done. You have reached the end of this module on
react JSX advanced patterns and testing. Let’s take a few minutes to review
where you have learned so far. You began the module with
an in depth lesson on JSX, you were presented with the distinction
between components and elements. You learned that components are functions
that take data or props as an input and return a tree of elements as output. You also learned that elements are just
plain javascript objects that offer a lightweight representation
of the dom and let react update your user interface
in a fast and predictable way. Next you discovered the importance
of component composition and the use of the children prop. You were introduced to containment and
specialization. The two main properties that
component composition has. You learn that containment is a technique
that is applicable to components that don’t know their
children ahead of time. Like a dialogue or a sidebar and that it uses the special children prop two
pass elements directly as their content. You were also introduced to
specialization, a technique that allows you to define components of
special cases of other components, like creating a confirmation
dialog based on a dialogue. Then you moved on to a lesson about
manipulating children dynamically in JSX. Here you were introduced to
a couple of new react APIs, react dot clone element and
react dot children. You learned that reactor dot clone
element clones and returns a new element allowing you to manipulate and
transform elements directly in your JSX. You also learned the react dot
children dot map is useful for children manipulation and that when
used in conjunction with react dot clone element enables a powerful composition
model for creating flexible components. You work through a practical example of
those to APIs where a rogue component was implemented to separate
its children evenly. Finally, you were introduced to
the spread operator in react, you learned that the spread operator
enables two main operations and objects, copying and merging. You then saw how react uses
that operator to spread all the props instead of having to
type them manually one by one. Finally, you were presented some practical
examples that illustrated how the spread operator allows the creation
of flexible components. You then moved on to a lesson on advanced
patterns to reusing common behavior. The lessons started with an overview
of cross cutting concerns and react. You learned that cross cutting concerns
refers to generic functionality that is not related to the application business
logic and that is needed in many places. Like handling errors,
authenticating or fetching data. You understood why components despite
being the primary unit of code reuse and react don’t fit this type of logic. After that you were presented with two
techniques for cross cutting concerns. The first technique you were introduced to
was the higher order component technique, which you learned enables
a powerful abstraction for creating cross cutting concerns. You were also presented with an example of
how data fetching can be abstracted using this technique. As part of a practical lesson
on higher order components. You learned that a higher order component
is just a function that takes a component and returns a new one. You were presented with a required code
structure to create a higher order component and examined an application of
a higher order component that handled the position of the mouse
pointer on the screen. Then you learned about
the second technique for cross cutting concerns
called render props. Which is a special prop you add to
your components with a particular attribute of being a function
that returns a react element. You discovered that as opposed
to higher order components, the new props are injected dynamically
as the parameters of the function. And worked through a practical example
where the render props technique was used to abstract the functionality
of fetching data from a server. The module ended with a lesson
on component testing using react testing library. The lesson began with a comprehensive
explanation as to why react testing library is the recommended tool for
your tests. You learned that to guarantee that
your applications work as intended, a suite of automated tests is crucial. You were presented with best
practices when it comes to testing, seeing how the react testing library has
been designed with all of them in mind. Finally, you were introduced to
a basic example of a test with gest the recommended test runner and react testing library to illustrate
the basic scaffolding of a test. The lesson and component testing
concluded with a practical application of tests in
a real world example. With this, you learned how well designed
tests can catch errors in your code, providing you with the necessary
context to fix them. You also discovered a more complex
application that can be easily tested with a few lines of code. Then you were presented with several APIs
from react testing library like screen to query on the global document in different
query types like querying by text or querying by role. Lastly, you learned about different
matters for your expectations and assertion, like to have been called for
mock functions and to have attributes for attributes in your elements. Fantastic work congrats for
getting to this point in the course. It’s time to use everything
you have learned so far and build some amazing applications.

Quiz: Module quiz: JSX and Testing

What are some of the features of component containment? Select all that apply.

What are the props that all components have by default?

What is a React Element? Select all that apply.

Assuming you have the below component, what are all the features implemented from component composition with children?

What are some of the use cases that the React.cloneElement API allows you to achieve? Select all that apply.

Assuming you have the following Row component that uses React.Children.map to perform some dynamic transformation in each child element, in order to add some custom styles, what’s wrong about its implementation?

Assuming you have the following set of components, what would be logged into the console when clicking the Submit button that gets rendered on the screen?

Among the below options, what are valid solutions to encapsulate cross-cutting concerns? Select all that apply

What does the screen utility object from react-testing-library represent when performing queries against it?

When writing tests with Jest and react-testing-library, what matcher would you have to use to assert that a button is disabled?

Reading: Additional resources

Reading