Building Reusable React Components
Reusable components are the foundation of modern frontend development. By creating small, self-contained building blocks, you can dramatically increase development speed, reduce duplicated code, and ensure consistency across your application.
In a Liferay project, reusable components are particularly valuable because they can be developed once inside a client extension and then deployed across multiple sites, pages, etc. without rewriting logic. This not only improves delivery timelines but also ensures your user interface and user experience remain consistent, regardless of where the component is used.
However, building from scratch comes with trade-offs. Purely custom components give you complete flexibility but require extra work to make them accessible, responsive, and aligned with Liferay’s look and feel. Leveraging Clay React—Liferay’s native component library—can significantly accelerate this process, giving you ready-to-use, accessible, and visually consistent components that seamlessly blend with out-of-the-box Liferay features.
Fundamentals of Reusable Components
A good reusable component follows three key principles:
- Encapsulation: The component’s structure, behavior, and style are self-contained.
- Reusability: The component can be placed in different contexts without major rewrites.
- Composability: The component can be combined with other components to form more complex features.
When designing a component, think of it as a black box. It should do its job without depending heavily on its surroundings. This keeps components flexible and easier to maintain.
Building React Components in a Client Extension
Although these components will live in a Liferay client extension, the process of building them is identical to any standalone React app:
- Create a .jsx or .tsx file for your component.
- Define its structure, style, and logic inside that file.
- Export it so it can be imported into your entry point.
- Render it via your extension’s main index.js or App.jsx.
Building a React component inside a Liferay client extension doesn’t require special Liferay knowledge. The Liferay-specific skills come into play when you want your component to interact with the platform (e.g., styling with Clay, listening for Liferay events, or calling Liferay’s headless APIs).
How much you leverage these Liferay features directly correlates to how much autonomy you want to maintain for the React components themselves. For example, if your goal is to have a reusable component that will only ever be used in the context of a Liferay application, then it makes sense to take advantage of the provided styling, layouts, and events.
Managing Props, State, and Events
Props, state, and events are critical aspects of React applications.
Props
Props let you pass data into a component from its parent, making it reusable for different scenarios.
State
State holds the data that changes over time within the component. Each component should have its own independent state, ensuring that updates in one don’t accidentally affect another.
Events
Events describe user actions (clicks, input changes, etc.) and state changes in a component. When working with JavaScript applications that are running in a browser, you can take advantage of browser event propagation to create a highly dynamic and “reactive” application. The main benefit of this feature is that it allows multiple independent components to respond to each other’s changes without requiring a direct parent-child relationship.
Interacting with the DOM
React normally manages the DOM for you via its virtual DOM, but there are valid cases for direct DOM access:
- Integrating with third-party libraries that require element references (e.g., Open Street Maps).
- Selecting Liferay-generated elements that aren’t part of your component’s tree.
- Working with elements identified by Liferay-specific IDs, classes, or namespaces.
In these cases, make sure to use the React hooks useRef and useEffect to safely interact with DOM elements after render. It is a best practice to avoid altering the global DOM structure in a way that could impact other components or Liferay functionality.
Clarity’s Custom React Components
The Clarity development team has identified the different custom element client extensions that they plan to build to meet the requirements of the business. After surveying the components that are available via Liferay, they have determined that not all the elements necessary for a solution are available out of the box. The team has decided that the client extension that will be responsible for rendering a map with the distributors' locations is something that will need to be built by the team. The consensus among the team is that this should be the only component that needs to be completely custom built. The other elements can leverage Liferay’s out-of-the-box tools and libraries.
Conclusion
To build reusable React components within a Liferay client extension, you should follow standard React development patterns for managing structure, props, and state, and events. The key decision for developers is balancing the flexibility of a purely custom component against the efficiency and consistency gained by leveraging Liferay's native tools and libraries. This strategic approach ensures the creation of maintainable and visually cohesive applications.
In the next lesson, you’ll learn more about using Clay React components.
Capabilities
Product
Education
Knowledge Base
Contact Us