diff --git a/documentation/blog/2023-10-23-js-substring.md b/documentation/blog/2024-12-31-js-substring.md similarity index 79% rename from documentation/blog/2023-10-23-js-substring.md rename to documentation/blog/2024-12-31-js-substring.md index 0ad6d4c5e59b..d2573ecf0b3d 100644 --- a/documentation/blog/2023-10-23-js-substring.md +++ b/documentation/blog/2024-12-31-js-substring.md @@ -4,14 +4,18 @@ description: We'll learn how to use JavaScript substring method to extract subst slug: javascript-substring-method authors: abdullah_numan tags: [javascript] -image: https://refine.ams3.cdn.digitaloceanspaces.com/blog/2023-10-23-js-substring/social.png +image: https://refine.ams3.cdn.digitaloceanspaces.com/blog/2023-10-23-js-substring/social-2.png hide_table_of_contents: false --- +**This article was last updated on December 31, 2024, to include common mistakes to avoid when working with JavaScript’s substring() method, such as skipping the endIndex or misunderstanding negative indices. A Frequently Asked Questions section has also been added to clarify common issues and provide practical examples.** + ## Introduction This post is about how to effectively use the `String.prototype.substring()` method in JavaScript. We go through a few examples to understand how it works, play around to observe a few patterns and explore the quirks. +### What is JavaScript `substring()`? + JavaScript `substring()` is a `String` method that is typically used to extract and store part of a string. During the extraction, the original string remains intact, and the target part is returned as a new string. `String.prototype.substring()` is handy for producing substrings of characters from a point to another of a parent string. The substring may be from the beginning, in-between specified indexes or from the tail. @@ -22,6 +26,7 @@ In the later half of the post, we discuss some of the nuances associated with `s Step by step, we'll cover the following topics: +- [Introduction](#introduction) - [JavaScript `substring()` Method](#javascript-substring-method) - [`Array.prototype.substring()` Method Signature](#arrayprototypesubstring-method-signature) - [JavaScript `substring()` with `startIndex` Only](#javascript-substring-with-startindex-only) @@ -35,6 +40,11 @@ Step by step, we'll cover the following topics: - [`String.prototype.substring()` Comparison](#stringprototypesubstring-comparison) - [JavaScript `substring()` vs `slice()`](#javascript-substring-vs-slice) - [JavaScript `substring()` vs `substr()`](#javascript-substring-vs-substr) +- [Common Mistakes When Working With substring()](#common-mistakes-when-working-with-substring) + - [Skipping endIndex](#skipping-endindex) + - [Reversed Indices Confusion](#reversed-indices-confusion) +- [Frequently Asked Questions](#frequently-asked-questions) +- [Summary](#summary) ## JavaScript `substring()` Method @@ -257,6 +267,91 @@ console.log(mnemonic.substr(-10, 12)); // "padlocked." In this case, only `10` characters are picked because `2` out of targeted `12` are not available in the last `10` characters. +## Common Mistakes When Working With substring() + +Over the years, I have encountered a few mistakes developers make using the substring() method. Let me outline them below. + +### Skipping endIndex + +A lot of us forget that the endIndex is optional. If you don’t pass it, substring() just extracts everything from the startIndex to the end of the string. That’s OK most of the time, but if you accidentally leave it out when you meant to extract a certain range, it may mess things up. + +```tsx +const text = "Hello, World!"; +console.log(text.substring(7)); // "World!" +console.log(text.substring(7, 12)); // "World" +``` + +Before using substring(), I double-check whether I really need the endIndex or not. + +```tsx +const text = "Hello, World!"; +console.log(text.substring(-5)); // "Hello, World!" (negative becomes 0) +console.log(text.slice(-5)); // "orld!" +``` + +What I do now: In cases when I need negative indexing, I stick with slice(). + +### Reversed Indices Confusion + +If the value of startIndex is greater than the value of endIndex, substring() will swap them. If you’re not paying attention, it can lead to unexpected behavior. + +```tsx +const text = "Hello, World!"; +console.log(text.substring(12, 7)); // "World" (indices are swapped) +console.log(text.slice(12, 7)); // "" (slice doesn't swap, just returns an empty string) +``` + +What I do now: Always ensure that startIndex <= endIndex whenever using substring(). + +## Frequently Asked Questions + +**What if startIndex equals endIndex?** + +You will get an empty string because substring() does not include the endIndex. + +```tsx +const text = "Hello, World!"; +console.log(text.substring(5, 5)); // "" +``` + +**Can substring() change the original string?** + +Nope - it’s non-destructive, simply returning the new string and leaving the original alone. + +```tsx +const text = "Hello, World!"; +const result = text.substring(7); +console.log(result); // "World!" +console.log(text); // "Hello, World!" +``` + +**What if the indices are out of range?** + +If the indices exceed the length of the string, substring() will simply stop at the string’s end. + +```tsx +const text = "Hello"; +console.log(text.substring(2, 10)); // "llo" +console.log(text.substring(10, 20)); // "" +``` + +**How does substring() differ from slice()?** + +Both do similar things, but here’s the difference: + +- substring() swaps indices if startIndex > endIndex. slice() doesn’t. +- slice() supports negative indices; substring() doesn’t. + +```tsx +const text = "Hello, World!"; +console.log(text.substring(7, 12)); // "World" +console.log(text.slice(-5)); // "orld!" +``` + +**Negative Indices Misconception** + +Here’s a big one: substring() doesn’t handle negative numbers. If you pass in a negative startIndex or endIndex, it will just treat them as 0. I’ve seen people confuse this with slice(), which actually supports negative indices. + ## Summary In this post, we exercised the use of JavaScript `substring()` with some basic examples. We first learned that `substring()` is a `String` extraction method that returns a target portion from a parent string. We got familiar with the required `startIndex` argument whose value is included in the extracted substring, and also with the `endIndex` argument which indicates termination of the string. diff --git a/documentation/blog/2023-10-29-react-slick.md b/documentation/blog/2025-01-02-react-slick.md similarity index 89% rename from documentation/blog/2023-10-29-react-slick.md rename to documentation/blog/2025-01-02-react-slick.md index ad7245a18696..6d393b8bc7c2 100644 --- a/documentation/blog/2023-10-29-react-slick.md +++ b/documentation/blog/2025-01-02-react-slick.md @@ -4,10 +4,12 @@ description: We'll see how to use React Slick in your React projects through a s slug: react-slick authors: deborah_emeni tags: [react] -image: https://refine.ams3.cdn.digitaloceanspaces.com/blog/2023-10-29-react-slick/social.png +image: https://refine.ams3.cdn.digitaloceanspaces.com/blog/2023-10-29-react-slick/social-2.png hide_table_of_contents: false --- +**This article was last updated on January 2, 2025, to address common queries about React Slick and a dedicated section for Common Mistakes When Working with React Slick to improve usability and clarity.** + ## Introduction Developers need a visually appealing way to display or showcase multiple items, services, features, or products in a single space while maintaining a good user experience. That's where Carousels (interactive, rotating slideshows) come in to enable developers to achieve this by making it easy for their users to navigate through large amounts of information while improving the user experience. @@ -23,13 +25,8 @@ Steps we'll cover: - [Benefits of using React Slick](#benefits-of-using-react-slick) - [Demo: Getting Started with React Slick](#demo-getting-started-with-react-slick) - [Using React Slick](#using-react-slick) - - [Creating our carousel component](#creating-our-carousel-component) - [Building a Fashion Carousel with React Slick](#building-a-fashion-carousel-with-react-slick) - - [Creating Slides for the Carousel](#creating-slides-for-the-carousel) - - [Styling the Fashion Carousel](#styling-the-fashion-carousel) - - [Adding Arrow Navigation](#adding-arrow-navigation) - - [Adding Thumbnails](#adding-thumbnails) - - [Adding Responsiveness](#adding-responsiveness) +- [Common Mistakes When Using React Slick (and How to Avoid Them)](#common-mistakes-when-using-react-slick-and-how-to-avoid-them) ## Overview of React Slick @@ -698,6 +695,137 @@ Run your application and see how the carousel shrinks from 2 to 1 when it reache react slick +## Common Mistakes When Using React Slick (and How to Avoid Them) + +Over the years, I’ve seen (and made!) plenty of mistakes while working with React Slick. Let me share a few common ones and how to steer clear of them: + +### Forgetting the CSS Files + +This is a classic! React Slick doesn’t come styled out of the box. If you forget to include the slick.css and slick-theme.css files, your carousel won’t look right—it’ll function, but it’ll be pretty ugly. + +What to do: +Always add these imports in your code after installing slick-carousel: + +```tsx +import "slick-carousel/slick/slick.css"; +import "slick-carousel/slick/slick-theme.css"; +``` + +### Overloading the Carousel with Too Many Items + +Adding tons of slides can make the carousel sluggish, especially on mobile devices. Nobody likes a slow app, right? + +What to do: +Use the lazyLoad option to load only the visible slides: + +```tsx +const settings = { + lazyLoad: "ondemand", + // other settings +}; +``` + +### Misconfiguring Breakpoints + +I’ve often seen developers set breakpoints but forget to test them properly. This can result in carousels looking weird on different devices. + +What to do: +Test your responsive settings thoroughly. Here’s an example: + +```tsx +const settings = { + responsive: [ + { + breakpoint: 1024, + settings: { + slidesToShow: 2, + }, + }, + { + breakpoint: 600, + settings: { + slidesToShow: 1, + }, + }, + ], +}; +``` + +### Ignoring Accessibility + +Carousels can be a nightmare for users with disabilities if accessibility isn’t handled well. For instance, navigation arrows might not be keyboard-friendly. + +What to do: + +- Add aria-labels to navigation elements. +- Use React Slick’s built-in accessibility prop (it’s enabled by default): + +```tsx +const settings = { + accessibility: true, + // other settings +}; +``` + +By keeping these in mind, you’ll avoid headaches later on! + +### Performance Optimization Tips + +React Slick is great, but if you’re not careful, it can slow down your app. Here are some easy ways to keep it running smoothly: + +#### Use Lazy Loading + +Loading all the images at once can slow down the initial page load, especially if you’ve got a lot of slides. + +What to do: +Turn on lazy loading so images load only when they’re needed: + +```tsx +const settings = { + lazyLoad: "ondemand", + // other settings +}; +``` + +#### Optimize Your Images + +Large image files can kill performance. + +What to do: + +- Use optimized images (e.g., compress them with tools like TinyPNG). +- Use responsive image sizes for different screen widths. + +#### Limit Slide Animations + +Too many fancy animations can make your carousel feel slow, especially on older devices. + +What to do: +Stick to a simple transition and set a reasonable speed: + +```tsx +const settings = { + speed: 500, // milliseconds + cssEase: "ease-in-out", + // other settings +}; +``` + +#### Avoid Re-renders + +Re-renders can happen when props or state change unnecessarily. + +What to do: +Use React.memo for your carousel component if the slides don’t change frequently: + +```tsx +import React, { memo } from "react"; + +const MyCarousel = memo(() => { + return /* slides */; +}); +``` + ## Conclusion You've reached the end of this article, where we covered the following aspects of React Slick: what React Slick is, why developers need it, its core features, React Slick APIs and the benefits of using it. Additionally, we demonstrated two hands-on examples in which we created a carousel component using React Slick. React Slick is a user-friendly library with a wide range of features and advantages you can leverage to create carousels for simple and complex applications. diff --git a/documentation/docs/advanced-tutorials/forms/custom-form-validation.md b/documentation/docs/advanced-tutorials/forms/custom-form-validation.md index afa86aa784c8..10784e8c72cd 100644 --- a/documentation/docs/advanced-tutorials/forms/custom-form-validation.md +++ b/documentation/docs/advanced-tutorials/forms/custom-form-validation.md @@ -40,6 +40,8 @@ Now let's prepare a rule that checks if the titles of the posts are unique. We h ``` ```tsx live hideCode url=http://localhost:3000/posts/create +setInitialRoutes(["/posts/create"]); + // visible-block-start import { useForm, Create, CreateButton } from "@refinedev/antd"; import { Form, Input } from "antd"; @@ -61,10 +63,14 @@ interface PostUniqueCheckRequestQuery { // highlight-end const PostCreate: React.FC = () => { - const { formProps, saveButtonProps } = useForm(); + const { formProps, saveButtonProps } = useForm({ + defaultFormValues: { + title: "Test", + }, + }); // highlight-next-line - const [title, setTitle] = useState(""); + const [title, setTitle] = useState("Test"); // highlight-start const apiUrl = useApiUrl(); @@ -100,7 +106,8 @@ const PostCreate: React.FC = () => { }, { validator: async (_, value) => { - if (!value) return; + if (!value) + return Promise.reject(new Error("Please enter a title")); const { data } = await refetch(); if (data && data.data.isAvailable) { return Promise.resolve(); @@ -124,21 +131,30 @@ const PostCreate: React.FC = () => { // visible-block-end render( - ( -
-

This page is empty.

- -
- ), - create: PostCreate, - }, - ]} - />, + + + + +

This page is empty.

+ + + } + /> + } /> +
+
+
, ); ``` diff --git a/documentation/docs/data/hooks/use-infinite-list/_basic-usage-live-preview.md b/documentation/docs/data/hooks/use-infinite-list/_basic-usage-live-preview.md index 44deafb27c59..cd3e93f38546 100644 --- a/documentation/docs/data/hooks/use-infinite-list/_basic-usage-live-preview.md +++ b/documentation/docs/data/hooks/use-infinite-list/_basic-usage-live-preview.md @@ -55,10 +55,18 @@ setRefineProps({ resources: [ { name: "posts", - list: PostList, + list: "/posts", }, ], }); -render(); +render( + + + + } /> + + + , +); ``` diff --git a/documentation/docs/data/hooks/use-infinite-list/_filtering-live-preview.md b/documentation/docs/data/hooks/use-infinite-list/_filtering-live-preview.md index 6bf5673ef316..0cfb20b27f3a 100644 --- a/documentation/docs/data/hooks/use-infinite-list/_filtering-live-preview.md +++ b/documentation/docs/data/hooks/use-infinite-list/_filtering-live-preview.md @@ -88,10 +88,18 @@ setRefineProps({ resources: [ { name: "products", - list: ProductList, + list: "/products", }, ], }); -render(); +render( + + + + } /> + + + , +); ``` diff --git a/documentation/docs/data/hooks/use-infinite-list/_sorting-live-preview.md b/documentation/docs/data/hooks/use-infinite-list/_sorting-live-preview.md index 0a20b7aa8f60..90b41f739131 100644 --- a/documentation/docs/data/hooks/use-infinite-list/_sorting-live-preview.md +++ b/documentation/docs/data/hooks/use-infinite-list/_sorting-live-preview.md @@ -83,10 +83,18 @@ setRefineProps({ resources: [ { name: "products", - list: ProductList, + list: "/products", }, ], }); -render(); +render( + + + + } /> + + + , +); ``` diff --git a/documentation/docs/data/hooks/use-list/_basic-usage-live-preview.md b/documentation/docs/data/hooks/use-list/_basic-usage-live-preview.md index 11d9d9b5f593..a03ba9348486 100644 --- a/documentation/docs/data/hooks/use-list/_basic-usage-live-preview.md +++ b/documentation/docs/data/hooks/use-list/_basic-usage-live-preview.md @@ -51,10 +51,18 @@ setRefineProps({ resources: [ { name: "products", - list: ProductList, + list: "/products", }, ], }); -render(); +render( + + + + } /> + + + , +); ``` diff --git a/documentation/docs/data/hooks/use-list/_filtering-live-preview.md b/documentation/docs/data/hooks/use-list/_filtering-live-preview.md index 25a432bf90f9..f9eedc82007e 100644 --- a/documentation/docs/data/hooks/use-list/_filtering-live-preview.md +++ b/documentation/docs/data/hooks/use-list/_filtering-live-preview.md @@ -77,10 +77,18 @@ setRefineProps({ resources: [ { name: "products", - list: ProductList, + list: "/products", }, ], }); -render(); +render( + + + + } /> + + + , +); ``` diff --git a/documentation/docs/data/hooks/use-list/_pagination-live-preview.md b/documentation/docs/data/hooks/use-list/_pagination-live-preview.md index 75cd9d8ba8ad..6f16bc3c09b2 100644 --- a/documentation/docs/data/hooks/use-list/_pagination-live-preview.md +++ b/documentation/docs/data/hooks/use-list/_pagination-live-preview.md @@ -81,10 +81,18 @@ setRefineProps({ resources: [ { name: "products", - list: ProductList, + list: "/products", }, ], }); -render(); +render( + + + + } /> + + + , +); ``` diff --git a/documentation/docs/data/hooks/use-list/_sorting-live-preview.md b/documentation/docs/data/hooks/use-list/_sorting-live-preview.md index 963a8cc1ea72..40f1c8f3fd22 100644 --- a/documentation/docs/data/hooks/use-list/_sorting-live-preview.md +++ b/documentation/docs/data/hooks/use-list/_sorting-live-preview.md @@ -73,10 +73,18 @@ setRefineProps({ resources: [ { name: "products", - list: ProductList, + list: "/products", }, ], }); -render(); +render( + + + + } /> + + + , +); ``` diff --git a/documentation/docs/data/hooks/use-many/_basic-usage-live-preview.md b/documentation/docs/data/hooks/use-many/_basic-usage-live-preview.md index 6c1bafdc658c..0bdf52f24c64 100644 --- a/documentation/docs/data/hooks/use-many/_basic-usage-live-preview.md +++ b/documentation/docs/data/hooks/use-many/_basic-usage-live-preview.md @@ -54,7 +54,7 @@ const ProductList: React.FC = () => {