owned this note
owned this note
Published
Linked with GitHub
![Scalable-Strapi-React Apps with Typescript_ Best Practices](https://hackmd.io/_uploads/HJfknWEyR.jpg)
## Introducing TypeScript and Strapi for dynamic content handling
First, we will talk about the typical problems that arise when working with dynamic content in React apps that are powered by Strapi. The purpose of this section is to lay the groundwork for understanding the significance of dynamic content management in creating systems that are scalable and maintainable.
I will present TypeScript types and unions as essential resources for managing unpredictability in data structures and guaranteeing type safety, especially in the context of dynamic content handling.
React has emerged as a powerful tool in the quickly changing web development space for designing dynamic and captivating user interfaces. But making the most of React when paired with a robust content management system like Strapi becomes even more important. Together, they form a formidable team that makes it easier for developers to create scalable, maintainable systems that easily handle dynamic material.
In this comprehensive article, we want to explore the intricate realm of dynamic content management with the use of TypeScript and Strapi. We'll go through common issues with Strapi-powered React apps, highlighting the vital importance of efficient content management strategies.
## Goal
In this piece, we aim to do more than just solve problems. Rather, you will learn how to make use of unions and TypeScript types, which are tools that help you navigate the complexities of dynamic content. These technologies ensure type safety and provide unparalleled flexibility when working with variable data structures, especially in the context of dynamic content management.
So take a seat, and let's discuss the fundamentals of dynamic content management, where TypeScript and Strapi work together to build manageable, scalable, and ultimately pleasurable user experiences.
### Prerequisite
To maximize the value of this article you should have a basic understanding of the following before diving into the particulars of managing dynamic content with TypeScript and Strapi:
1. Fundamental understanding of React development: Understanding the principles of React, such as data models, state management, and JSX syntax, can help you better understand the ideas covered in this article.
2. Prior exposure to Strapi is optional, however, it will help you better understand the features and specific functionalities addressed in relation to dynamic content management.
3. Knowledge of TypeScript ideas: To properly appreciate how TypeScript is used to handle dynamic content in React apps, one should have a fundamental understanding of TypeScript concepts like types, interfaces, and unions.
4. Knowledge of the fundamentals of using the terminal to perform tasks. Your workflow will be improved as a result, and you will be able to actively participate in the article without experiencing feelings of being overwhelmed.
## TypeScript types and unions
This section will discuss TypeScript types and unions, which are useful tools for managing unpredictability in data structures and guaranteeing type safety, especially when handling dynamic content.
### Understanding TypeScript types
Variables, parameters, and return values can include different sorts of data, and TypeScript types offer a mechanism to explicitly define these types of data. Take a look at this straightforward example of establishing types for a user object:
```
type User = {
id: number;
name: string;
email: string;
};
```
In the example above, we have a *User* type with the attributes *name*, *email*, and *id* all of which have distinct data types, which are defined.
Type safety is provided by utilizing this type, which guarantees that any variable defined as a *User* must follow this structure.
### Managing variability with TypeScript unions
We can represent a value that can be any of numerous different kinds using TypeScript unions. Let's use an example where a function that takes in a string or a number as an input to demonstrate this:
```
function displayData(data: string | number) {
console.log(data);
}
// Usage examples
displayData("Hello"); // Output: Hello
displayData(42); // Output: 42
```
In the example above, the displayData function can accept either a string or a number, ensuring type safety while allowing for variability in the input data.
### Ensuring type safety in dynamic content handling
We can maintain type safety while controlling the unpredictability present in dynamic content handling scenarios by utilizing TypeScript types and unions. Let's look at an illustration of using dynamic data structures to handle Application Programming Interface (API) responses:
```
type ApiResponse = {
status: "success" | "error";
data: string | { id: number; name: string };
};
// Example API response
const response: ApiResponse = {
status: "success",
data: { id: 1, name: "John Doe" },
};
if (response.status === "success") {
// Handle successful response
console.log("User:", response.data.name);
} else {
// Handle error response
console.error("Error occurred:", response.data);
}
```
Above, we define an *API response* type with two properties: a data property that can be an object with the properties id and name and a status property that can be either *success* or *error*. In spite of variations in data structure, this guarantees that we manage API answers securely and efficiently.
## Understanding dynamic zones in Strapi
In this section, we take a tour through the Strapi framework's dynamic zones feature, which are essential elements for handling changeable content structures and give developers a range of options when it comes to structuring and displaying material.
This is made quite clear on the strapi website's front page. “Manage Any Content
Anywhere. The leading open-source headless CMS. 100% JavaScript / TypeScript and fully customizable.”
![Strapi-Motto: Manage Any Content
Anywhere](https://hackmd.io/_uploads/HknnbmNJR.png)
### Step 1.
To get started, create a new Strapi project. The simplest method to begin a new Strapi project is to install it using the Strapi Command Line Interface (CLI). There are other ways to get started as well, such as using the starting CLI.
```
1. yarn create strapi-app Strapi-TypeScript-App --quickstart
2. Or
3. npx create-strapi-app Strapi-TypeScript-App --quickstart
```
![Strapi Info](https://hackmd.io/_uploads/By-hSBVyR.png)
The code snippets above will create a Strapi-TypeScript-App Folder with all dependencies in it, by default, a server should be running but if it’s not serving, change the directory using your terminal into the Strapi-TypeScript-App folder via “cd Strapi-TypeScript-App\”.
You should see similar images like the ones below if the server runs by default, as it is supposed to:
![Strapi server is loading on the terminal.](https://hackmd.io/_uploads/HkzAZcEkR.png)
![Strapi server is loading on the terminal.](https://hackmd.io/_uploads/HklxfcEyR.png)
![Strapi server is loading on the terminal.](https://hackmd.io/_uploads/B18xMqV1R.png)
### Step 2.
But if it doesn’t, you can start the admin panel using the commands below, and it should be done inside the directory of Strapi in our case:
![How to manually turn on strapi server](https://hackmd.io/_uploads/rJe2csJZMC.png)
```
npm run develop
# OR
yarn run develop
```
This ought to open the address in a new browser window.
http://localhost:1337/admin/auth/register-admin
You can register as an administrator so you will be able to access the dashboard, ensure to fill out the form with accurate details
![Strapi admin registration page](https://hackmd.io/_uploads/SkGMf9EyC.png)
### Defining Dynamic Zones
Essentially, dynamic zones are areas of the Strapi interface that are configured so that developers can carefully select and organize different types of material in a dynamic manner. These zones give content producers a blank canvas on which to dynamically establish the composition and organization of their work, allowing them to easily modify and develop their content strategies.
Practically speaking, dynamic zones enable developers to design adaptable content models that support a variety of content kinds, from straightforward text fields to intricate media galleries and interactive elements. Dynamic zones give content creators the ability to create dynamic and engaging user experiences that are customized to meet their unique requirements by providing a modular and flexible approach to content creation.
Let's see how dynamic zones are created in the Strapi admin interface. Developers can use the Content Types Builder by entering into the Strapi dashboard and choosing the appropriate content type, like "Article" for a news website or "Property" for a real estate platform. Developers can create dynamic zones by adding recurring elements like rich text editors, text fields, and image galleries inside the content type settings. With the help of these dynamic zones, content producers can dynamically modify the arrangement of every article or real estate listing, guaranteeing a personalized and intuitive content management interface.
Strapi Dashboard:
![Strapi dashboard ](https://hackmd.io/_uploads/rkLQf9VyA.png)
Content Type Builder:
![Strapi dashboard: Content-Type Builder](https://hackmd.io/_uploads/rklgv_nxC.png)
### Role in Handling Changeable Content Frameworks
It is impossible to exaggerate the importance of dynamic zones in handling changeable content structures. These zones are the foundation of Strapi's content management system, offering a strong framework for dynamically arranging and presenting content.
Dynamic zones give content management operations unmatched flexibility by enabling developers to design and customize content structures on the fly. Dynamic zones provide developers with the resources they need to bring their ideas to life, whether they're organizing a blog post with movable text, photo, and video parts or making a product page with dynamic pricing and specifications.
### Advantages and possible complexities
Although dynamic zones have many benefits, such as scalability, flexibility, and reusability, there are certain challenges that developers must overcome. Developers may find it difficult to maintain a large number of dynamic zones, maintain consistency across various content parts, and maximize performance.
However, developers can fully utilize dynamic zones in their content management workflows by comprehending these intricacies and putting best practices into effect. With Strapi, developers can unleash new possibilities in content management through dynamic zones that streamline content creation processes and create tailored user experiences.
## Using TypeScript types for Strapi response typing
It is important that we comprehend the structure of the data supplied by Strapi before we begin entering our responses. Typically, Strapi provides JSON objects that represent several kinds of content, like user profiles, products, and articles. We are able to determine the attributes and the corresponding data types by examining the response structure.
We will have to create an API endpoint using strapi content-type builder.
### Step 1.
We will navigate to strapi dashboard and click on *content-type builder*, after that we will create a new *collection type* which will be named *product*.
![Creation of a collection type called product.](https://hackmd.io/_uploads/ByITpkWzR.png)
We will then ensure to disable the *Draft & Publish* checkbox by clicking the *ADVANCED SETTINGS*, and then unchecking the *Draft & Publish* as you have seen in the image below.
![Configurations advanced settings](https://hackmd.io/_uploads/HkFDRJWfA.png)
Click continue and *Select a field for your collection* in our case we will use *Text* three times.
![Selection field image](https://hackmd.io/_uploads/Byfsyg-GA.png)
Click on *Text* and fill in *Author* and click *Finish* repeat the process so you can create *content* and *title* field.
![Add new text field image](https://hackmd.io/_uploads/HyrDxl-f0.png)
After you have done that navigate to *Content Manager* in your strapi dashboard so we can populate the content type we just created with data, you should see a dashboard similar to the one below.
![Content Manager: creating a data entry for the product collection type.](https://hackmd.io/_uploads/B1utWgbG0.png)
Click the button *Create new entry* after you do that repeat the process to create more entries.
![Entry made to the collection type](https://hackmd.io/_uploads/SJqXGgZzA.png)
After creating so many entries and populating your dashboard with data, which is stored in the Strapi SQLite database, you don't need to worry about that.
![Display of the total entries](https://hackmd.io/_uploads/BJ6-XxWzR.png)
We will then have to make sure we can access this data from the API endpoint we just created.
Navigate to the section called *Settings* and then move down to the section called *USERS & PERMISSIONS PLUGINS* click on *roles*, then click on *public* then click on *product* then check the boxes *find* and *find one* and finally click save, now our API endpoint is ready.
![Settings/Roles/Products](https://hackmd.io/_uploads/SJFFVg-MR.png)
If you followed the tutorial actively, you should be able to access your data from this URL endpoint *http://localhost:1337/api/products*.
![Strapi api endpoint with data on the screen image](https://hackmd.io/_uploads/HJkJUx-GC.png)
### Defining TypeScript interfaces
We can define TypeScript interfaces to describe our data after we have a firm grasp on the response structure. Interfaces define the types and properties of things, serving as blueprints for them. Let's look at an illustration:
To define our TypeScript interface to collect data from our Strapi API end-point, we will navigate to our text editor and create some directories in the root directory where Strapi is located. Our first will be:
1. Datacollections/datafetch.ts
2. funtions/fetchprod.ts
3. interfaces/Products.ts
![Screenshot of this artcile visual studio code workspace](https://hackmd.io/_uploads/HJqLdl-zC.png)
```
//interfaces/Products.ts
// Define the TypeScript interface for the Product
export interface Product {
id: number;
title: string;
content: string;
author: string;
createdat: Date;
}
```
We will specify the characteristics of Product object, including their corresponding data types, in this interface. These properties include id, title, content, author, and createdAt.
### Typing Strapi Response Functions
We will then implement our interfaces in the functions that are in charge of obtaining data from Strapi. We make sure that the provided data complies with the specified interface by typing these routines. Let's examine how we can make this happen:
In this section, if you notice we imported *axios* since you are using what we are using for the first time I guess we have to install *axios* module.
We will have to open our terminal in the text editor, mine is VS code so I will just press **( ctrl + \` )**
Once that is opened just copy and paste the command below, in the root directory, not inside the Strapi, be very careful here, if you are one directory below the root directory you could move up the directory using the **cd ..** command:
![change of directory and install axios library](https://hackmd.io/_uploads/rJxAjxZMC.png)
```
npm install axios
```
```
//functions/fetchprod.ts
import axios from 'axios';
import { Product } from '../interfaces/Products';
const BASE_URL = 'http://localhost:1337'; // Replace with your Strapi base URL
export const ProductService = {
async fetchProduct(id: number): Promise<Product> {
try {
const response = await axios.get<Product>(`${BASE_URL}/api/products/${id}`);
return response.data;
} catch (error) {
console.error('Error fetching product:', error);
throw error;
}
}
};
```
The *fetchprod* function is used in this example to retrieve product specifications from Strapi API and to specify that the returned data must comply with the product interface earlier established.
### Handling optional properties
Occasionally, some of the properties in our answer might be optional. The '?' syntax in TypeScript enables us to construct optional properties. Let's add optional properties to our interface by updating it:
```
export interface Product {
id: number;
title: string;
content: string;
author: string;
createdat: Date;
updatedat?: Date;
}
```
The *updatedat* attribute is indicated as optional in this instance, meaning that the answer may or may not contain it
To ensure that our endpoint works properly we will write a script to fetch the data from our terminal.
```
// Datacollection/datafetch.ts
import { ProductService } from '../functions/fetchprod'; // Adjust the import path as needed
async function testFetchProduct() {
try {
const productId = 3; // Replace with the ID of the product you want to fetch
const product = await ProductService.fetchProduct(productId);
console.log('Product:', product);
} catch (error) {
console.error('Error:', error);
}
}
testFetchProduct();
```
We have to always take note of the *productId* and the *id* number on our strapi product collection type, if the *id* you are trying to fetch doesn't exist, it will throw an error. So if we eventually delete some entries from our strapi product collection type we have to update the script too.
We always ensure that our Strapi server is running before trying to fetch data from our APi endpoint.
![Fetched data on the terminal from strapi api endpoint](https://hackmd.io/_uploads/SyFM4EMM0.png)
### Facilitating seamless integration with React
We enable smooth interaction with React applications that leverage Strapi by specifying TypeScript interfaces for Strapi answers. Typed replies reduce the chance of runtime errors and increase developer efficiency by providing IntelliSense help and type-checking.
In the next examples, we will delve deeper into sophisticated type strategies and recommended practices for using TypeScript to handle Strapi answers.
## Handling unknown components with TypeScript unions
It is rather typical in web development, particularly in content management systems (CMS) like Strapi, to deal with dynamic content whose component types are not preset. TypeScript unions offer a strong way to build adaptable data models that support various content data models in these kinds of situations.
### Understanding TypeScript unions
Using a TypeScript union type, we can represent a value that can be one of several different types. The *|* operator is used to specify it in between the types. As an illustration:
```
type MyType = string | number | boolean;
```
Here, *MyType* can be either a string, a number, or a boolean.
### Relevance in dynamic content scenarios
Content data models in applications driven by CMS can differ widely. A blog post, for example, could have several data models, such as text, pictures, videos, or even unique elements that the user has created.
It is imperative to manage these different data models' kinds dynamically while fetching and rendering such dynamic content. TypeScript unions offer a sophisticated way around this.
### Real-world examples
Let's look at a straightforward illustration of content rendering in a blog post. A TypeScript interface can be used to represent each component, and the post's content can be expressed as a union of these interfaces.
```
// interfaces/ProductComponents.ts
export interface ProductComponent {
id: number;
title: string;
content: string;
createdBy: string;
image: string | null;
}
```
Now you can iterate over the data models and handle each type appropriately when producing the content of a blog post:
```
// typescriptUnionDynamicContentHandling/populateDynamicArrays.ts
import axios from "axios";
import { ProductComponent } from "../interfaces/ProductComponents";
const BASE_URL = "http://localhost:1337";
async function fetchProductComponents(): Promise<ProductComponent[]> {
try {
const response = await axios.get<any>(`${BASE_URL}/api/products?populate=*`);
const products = response.data.data;
const components: ProductComponent[] = products.map((product: any, index: number) => {
const image = product.attributes.images?.data?.[0]?.attributes.url || null;
return {
id: index + 1,
title: product.attributes.Title,
content: product.attributes.content,
createdBy: product.attributes.Author,
image: image
};
});
return components;
} catch (error) {
console.error('Error fetching product components:', error);
throw error;
}
}
// Usage
fetchProductComponents().then((components) => {
console.log(components);
}).catch((error) => {
console.error(error);
});
```
Ensure your Strapi server is running locally before proceeding with this article.
To run the script above navigate the directory *typescriptUnionDynamicContentHandling/*, the command below.
```
cd typescriptUnionDynamicContentHandling/
```
You may need to change the above depending on where you are in your directory on your terminal.
Then use this to run the script above:
```
ts-node .\populateDynamicInArray.ts
```
You should have a result like the one below.
![Fetched data from strap api on terminal with typescript unions used stored in an array.](https://hackmd.io/_uploads/S1uRGYUMC.png)
### Benefits of TypeScript unions
1. Type Safety: TypeScript unions ensure type safety, preventing unexpected data types from slipping into your code.
2. Flexibility: They allow you to handle dynamic content with ease, accommodating various component types without boilerplate code.
3. Readability: By explicitly defining possible component types, your code becomes more readable and self-explanatory.
As we leverage TypeScript unions, you can build robust and flexible applications that seamlessly handle dynamic content in CMS-driven environments.
## Conclusion
The significance of TypeScript types and unions for dynamic content management in Strapi-React projects has been discussed in this article. For scalable systems, TypeScript provides a strong typing system that improves code readability and guarantees type safety.
Understanding TypeScript types, using unions to handle dynamic content, and practical examples showing how to apply them in flexible data structures are some of the key ideas presented.
In today's web development, dynamic content management is essential, and TypeScript unions and types allow for efficient administration without sacrificing code clarity or type safety.
The significance of type safety, adaptability using unions, and readability through unambiguous interfaces are among the important lessons learned. Clear interface definition, working with unions to handle unknown data models, and promoting communication and cooperation are all examples of best practices.
Developers can create more durable and manageable apps for efficiently handling dynamic content by utilizing TypeScript types and unions. Stay curious, keep coding, and have fun creating!
## Additional Resources
1. [Complete Github Repository](https://github.com/Alpheus-godswill1/Dynamic-Content-Handling-with-TypeScript-and-Strapi.git)
2. [Axios Documentation](https://axios-http.com/docs/intro)
3. [TypeScript Interface Documentation](https://www.typescriptlang.org/docs/handbook/typescript-tooling-in-5-minutes.html#interfaces)
4. [Strapi Quick Start Guide](https://docs.strapi.io/dev-docs/quick-start)