<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bidisha Das</title>
    <description>The latest articles on DEV Community by Bidisha Das (@officialbidisha).</description>
    <link>https://dev.to/officialbidisha</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F840444%2F4f61c35f-66c3-49f2-9d93-e665193106df.jpg</url>
      <title>DEV Community: Bidisha Das</title>
      <link>https://dev.to/officialbidisha</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/officialbidisha"/>
    <language>en</language>
    <item>
      <title>I Built a Simple RAG App with LangChain, OpenAI, and Pinecone</title>
      <dc:creator>Bidisha Das</dc:creator>
      <pubDate>Sun, 12 Jul 2026 19:22:27 +0000</pubDate>
      <link>https://dev.to/officialbidisha/i-built-a-simple-rag-app-with-langchain-openai-and-pinecone-j73</link>
      <guid>https://dev.to/officialbidisha/i-built-a-simple-rag-app-with-langchain-openai-and-pinecone-j73</guid>
      <description>&lt;p&gt;Large language models know a lot, but they do not automatically know the contents of our private files, company documents, notes, or recently written articles.&lt;/p&gt;

&lt;p&gt;This is where Retrieval-Augmented Generation, commonly called RAG, becomes useful.&lt;/p&gt;

&lt;p&gt;In this project, I built a small RAG application that:&lt;/p&gt;

&lt;p&gt;Reads a text document.&lt;br&gt;
Breaks the document into smaller sections.&lt;br&gt;
Converts those sections into numerical representations called embeddings.&lt;br&gt;
Stores the embeddings in Pinecone.&lt;br&gt;
Finds the most relevant sections when a user asks a question.&lt;br&gt;
Gives those sections to an AI model so it can produce a grounded answer. A grounded answer is an answer based on the retrieved source material. RAG reduces unsupported answers, but it does not guarantee that every response will be correct&lt;br&gt;
I used:&lt;/p&gt;

&lt;p&gt;Python for the application&lt;br&gt;
LangChain to connect the different steps&lt;br&gt;
OpenAI embeddings to represent text as numbers&lt;br&gt;
Pinecone to store and search those embeddings&lt;br&gt;
uv to manage the Python project and dependencies&lt;br&gt;
In this article, I will explain how the application works, how the different components fit together, and what I learned while debugging it.&lt;/p&gt;

&lt;p&gt;What Is RAG?&lt;br&gt;
Press enter or click to view image in full size&lt;/p&gt;

&lt;p&gt;RAG Pipeline&lt;br&gt;
Imagine that you are taking an open-book examination.&lt;/p&gt;

&lt;p&gt;Without a book, you answer only from memory. You may know the answer, but you may also forget something or provide incorrect information.&lt;/p&gt;

&lt;p&gt;Press enter or click to view image in full size&lt;/p&gt;

&lt;p&gt;Debugging using LangSmith&lt;br&gt;
With an open book, you can:&lt;/p&gt;

&lt;p&gt;Read the question.&lt;br&gt;
Search for the relevant page.&lt;br&gt;
Use that information to write the answer.&lt;br&gt;
A RAG application works in a similar way.&lt;/p&gt;

&lt;p&gt;The language model is the person answering the question. The vector database acts like a searchable book. Before answering, the application finds the most relevant information and gives it to the model.&lt;/p&gt;

&lt;p&gt;The model does not need to memorize the entire document. It only receives the sections that are likely to contain the answer.&lt;/p&gt;

&lt;p&gt;The Two Main Parts of a RAG Application&lt;br&gt;
A basic RAG application has two phases.&lt;/p&gt;

&lt;p&gt;Phase 1: Ingestion&lt;br&gt;
Ingestion means preparing the documents so that they can be searched later.&lt;/p&gt;

&lt;p&gt;Text document&lt;br&gt;
      ↓&lt;br&gt;
Load the document&lt;br&gt;
      ↓&lt;br&gt;
Split it into smaller chunks&lt;br&gt;
      ↓&lt;br&gt;
Convert each chunk into an embedding&lt;br&gt;
      ↓&lt;br&gt;
Store the embeddings in Pinecone&lt;br&gt;
This process usually runs when documents are added or updated.&lt;/p&gt;

&lt;p&gt;Phase 2: Retrieval and Answer Generation&lt;br&gt;
This phase runs whenever a user asks a question.&lt;/p&gt;

&lt;p&gt;User question&lt;br&gt;
      ↓&lt;br&gt;
Convert the question into an embedding&lt;br&gt;
      ↓&lt;br&gt;
Search Pinecone for similar document chunks&lt;br&gt;
      ↓&lt;br&gt;
Add those chunks to the prompt&lt;br&gt;
      ↓&lt;br&gt;
Ask the language model to answer&lt;br&gt;
Keeping these phases separate makes the application easier to understand.&lt;/p&gt;

&lt;p&gt;Ingestion prepares the knowledge. Retrieval uses that knowledge.&lt;/p&gt;

&lt;p&gt;What Is an Embedding?&lt;br&gt;
Press enter or click to view image in full size&lt;/p&gt;

&lt;p&gt;Computers cannot directly compare the meaning of sentences in the same way people do.&lt;/p&gt;

&lt;p&gt;An embedding model converts text into a list of numbers called a vector.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;"How do I reset my password?"&lt;br&gt;
might become something that looks like:&lt;/p&gt;

&lt;p&gt;[0.12, -0.48, 0.77, 0.03, ...]&lt;br&gt;
The actual vector contains hundreds or thousands of numbers.&lt;/p&gt;

&lt;p&gt;Sentences with similar meanings usually receive vectors that are close to each other. This allows the application to search by meaning rather than only by exact keywords.&lt;/p&gt;

&lt;p&gt;Press enter or click to view image in full size&lt;/p&gt;

&lt;p&gt;How embeddings work in real.&lt;br&gt;
LangChain provides a standard interface for embedding models, while OpenAI’s text-embedding-3 models allow developers to control the number of dimensions returned.&lt;/p&gt;

&lt;p&gt;What Is Pinecone?&lt;br&gt;
Press enter or click to view image in full size&lt;/p&gt;

&lt;p&gt;Pinecone is a vector database.&lt;/p&gt;

&lt;p&gt;A normal database is excellent at questions such as:&lt;/p&gt;

&lt;p&gt;Find the user whose ID is 123.&lt;br&gt;
A vector database is useful for questions such as:&lt;/p&gt;

&lt;p&gt;Find the document sections whose meaning is closest to this question.&lt;br&gt;
Pinecone stores the document vectors and searches for the vectors that are closest to the user’s question.&lt;/p&gt;

&lt;p&gt;The Pinecone index and the embedding model must use the same vector dimension. Otherwise, Pinecone cannot store or compare the vectors.&lt;/p&gt;

&lt;p&gt;Project Structure&lt;br&gt;
Now that the basic idea is clear, let us look at how the application is structured and how each part of the pipeline works.&lt;/p&gt;

&lt;p&gt;My project contains two main Python files:&lt;/p&gt;

&lt;p&gt;rag-project/&lt;br&gt;
├── rag-gist/&lt;br&gt;
│   ├── ingest.py&lt;br&gt;
│   ├── main.py&lt;br&gt;
│   └── mediumblog.txt&lt;br&gt;
├── .env&lt;br&gt;
├── .gitignore&lt;br&gt;
└── pyproject.toml&lt;br&gt;
Here is what each file does:&lt;/p&gt;

&lt;p&gt;mediumblog.txt contains the source information.&lt;br&gt;
ingest.py loads and stores the document in Pinecone.&lt;br&gt;
main.py accepts a question and generates an answer.&lt;br&gt;
.env stores API keys.&lt;br&gt;
.gitignore prevents secrets from being committed.&lt;br&gt;
pyproject.toml contains the project dependencies.&lt;/p&gt;

&lt;p&gt;The project contains separate scripts for document ingestion and question answering.&lt;br&gt;
Step 1: Install the Dependencies&lt;br&gt;
I used uv to manage the project.&lt;/p&gt;

&lt;p&gt;The required packages can be installed with:&lt;/p&gt;

&lt;p&gt;uv add langchain \&lt;br&gt;
    langchain-community \&lt;br&gt;
    langchain-openai \&lt;br&gt;
    langchain-pinecone \&lt;br&gt;
    langchain-text-splitters \&lt;br&gt;
    python-dotenv&lt;br&gt;
The main packages have different responsibilities:&lt;/p&gt;

&lt;p&gt;langchain-openai connects LangChain to OpenAI models.&lt;br&gt;
langchain-pinecone connects LangChain to Pinecone.&lt;br&gt;
langchain-community provides document loaders.&lt;br&gt;
langchain-text-splitters provides tools for dividing documents into chunks.&lt;br&gt;
python-dotenv loads environment variables from a .env file.&lt;br&gt;
LLM libraries change quickly, so it is better to keep the generated lock file in the repository instead of relying only on version numbers written in an article.&lt;/p&gt;

&lt;p&gt;Step 2: Add the API Keys&lt;br&gt;
Create a .env file in the project root:&lt;/p&gt;

&lt;p&gt;OPENAI_API_KEY=your_openai_api_key&lt;br&gt;
PINECONE_API_KEY=your_pinecone_api_key&lt;br&gt;
Never upload this file to GitHub.&lt;/p&gt;

&lt;p&gt;Add it to .gitignore:&lt;/p&gt;

&lt;p&gt;.env&lt;br&gt;
.venv/&lt;br&gt;
&lt;strong&gt;pycache&lt;/strong&gt;/&lt;br&gt;
You can also create a safe example file called .env.example:&lt;/p&gt;

&lt;p&gt;OPENAI_API_KEY=&lt;br&gt;
PINECONE_API_KEY=&lt;br&gt;
This tells other developers which variables are required without exposing the real values.&lt;/p&gt;

&lt;p&gt;Step 3: Create the Pinecone Index&lt;br&gt;
Before running the ingestion script, create a dense Pinecone index.&lt;/p&gt;

&lt;p&gt;Pinecone does not generate the answer. Its job is to find the document chunks that are most relevant to the user’s question.&lt;/p&gt;

&lt;p&gt;For this project, I used:&lt;/p&gt;

&lt;p&gt;Index name: medium-blogs-embedding-index&lt;br&gt;
Dimension: 512&lt;br&gt;
Metric: cosine&lt;br&gt;
The dimension is important.&lt;/p&gt;

&lt;p&gt;The embedding model and the Pinecone index must use the same number of dimensions. Otherwise, Pinecone cannot store or compare the vectors.&lt;/p&gt;

&lt;p&gt;OpenAI embeddings can be used for semantic search by comparing the similarity between document and query vectors.&lt;/p&gt;

&lt;p&gt;Press enter or click to view image in full size&lt;/p&gt;

&lt;p&gt;The Pinecone index uses 512 dimensions, matching the embedding configuration in the Python code&lt;br&gt;
Step 4: Load and Store the Document&lt;br&gt;
The ingestion script reads the text file, divides it into chunks, converts each chunk into an embedding, and stores the result in Pinecone.&lt;/p&gt;

&lt;p&gt;Here is the ingestion script:&lt;/p&gt;

&lt;p&gt;from pathlib import Path&lt;br&gt;
from dotenv import load_dotenv&lt;br&gt;
from langchain_community.document_loaders import TextLoader&lt;br&gt;
from langchain_openai import OpenAIEmbeddings&lt;br&gt;
from langchain_pinecone import PineconeVectorStore&lt;br&gt;
from langchain_text_splitters import CharacterTextSplitter&lt;br&gt;
load_dotenv()&lt;br&gt;
INDEX_NAME = "medium-blogs-embedding-index"&lt;br&gt;
EMBEDDING_MODEL = "text-embedding-3-small"&lt;br&gt;
EMBEDDING_DIMENSION = 512&lt;br&gt;
def main() -&amp;gt; None:&lt;br&gt;
    print("Ingesting...")&lt;br&gt;
    file_path = Path(&lt;strong&gt;file&lt;/strong&gt;).with_name("mediumblog.txt")&lt;br&gt;
    if not file_path.exists():&lt;br&gt;
        raise FileNotFoundError(&lt;br&gt;
            f"Knowledge file was not found: {file_path}"&lt;br&gt;
        )&lt;br&gt;
    print("Loading document...")&lt;br&gt;
    loader = TextLoader(str(file_path), encoding="utf-8")&lt;br&gt;
    documents = loader.load()&lt;br&gt;
    text_splitter = CharacterTextSplitter(&lt;br&gt;
        chunk_size=1000,&lt;br&gt;
        chunk_overlap=0,&lt;br&gt;
    )&lt;br&gt;
    chunks = text_splitter.split_documents(documents)&lt;br&gt;
    print(f"Created {len(chunks)} text chunks")&lt;br&gt;
    embeddings = OpenAIEmbeddings(&lt;br&gt;
        model=EMBEDDING_MODEL,&lt;br&gt;
        dimensions=EMBEDDING_DIMENSION,&lt;br&gt;
    )&lt;br&gt;
    PineconeVectorStore.from_documents(&lt;br&gt;
        documents=chunks,&lt;br&gt;
        embedding=embeddings,&lt;br&gt;
        index_name=INDEX_NAME,&lt;br&gt;
    )&lt;br&gt;
    print("Ingestion complete.")&lt;br&gt;
if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    main()&lt;br&gt;
Run the script with:&lt;/p&gt;

&lt;p&gt;uv run python rag-gist/ingest.py&lt;br&gt;
The output should look similar to this:&lt;/p&gt;

&lt;p&gt;Ingesting...&lt;br&gt;
Loading document...&lt;br&gt;
Created 31 text chunks&lt;br&gt;
Ingestion complete.&lt;br&gt;
Press enter or click to view image in full size&lt;/p&gt;

&lt;p&gt;The ingestion script loaded the document, created 31 chunks, and stored them in Pinecone.&lt;br&gt;
Understanding the Ingestion Code&lt;br&gt;
Let us look at what the script is doing.&lt;/p&gt;

&lt;p&gt;Loading the Document&lt;br&gt;
loader = TextLoader(str(file_path), encoding="utf-8")&lt;br&gt;
documents = loader.load()&lt;br&gt;
The loader turns the text file into LangChain Document objects.&lt;/p&gt;

&lt;p&gt;A document usually contains:&lt;/p&gt;

&lt;p&gt;page_content: the actual text&lt;br&gt;
metadata: information such as the source filename&lt;br&gt;
Splitting the Document&lt;br&gt;
text_splitter = CharacterTextSplitter(&lt;br&gt;
    chunk_size=1000,&lt;br&gt;
    chunk_overlap=0,&lt;br&gt;
)&lt;br&gt;
Instead of embedding the entire document as one large block, we divide it into smaller chunks.&lt;/p&gt;

&lt;p&gt;Press enter or click to view image in full size&lt;/p&gt;

&lt;p&gt;Chunking is essential for context window : and token optimization. Instead of sending the entire document to the language model, the application sends only the sections that are most relevant to the question.&lt;br&gt;
This is important because a user’s question may only be related to one small part of the document.&lt;/p&gt;

&lt;p&gt;A chunk size of 1000 means that each section contains approximately 1,000 characters.&lt;/p&gt;

&lt;p&gt;For this first version, I used no overlap. In a stronger version, I would add some overlap so that information near the end of one chunk is also available at the beginning of the next chunk.&lt;/p&gt;

&lt;p&gt;Creating Embeddings&lt;br&gt;
embeddings = OpenAIEmbeddings(&lt;br&gt;
    model="text-embedding-3-small",&lt;br&gt;
    dimensions=512,&lt;br&gt;
)&lt;br&gt;
This code tells OpenAI to return embeddings with 512 dimensions.&lt;/p&gt;

&lt;p&gt;The dimensions option is supported by OpenAI’s text-embedding-3 family of models.&lt;/p&gt;

&lt;p&gt;Storing the Chunks&lt;br&gt;
PineconeVectorStore.from_documents(&lt;br&gt;
    documents=chunks,&lt;br&gt;
    embedding=embeddings,&lt;br&gt;
    index_name=INDEX_NAME,&lt;br&gt;
)&lt;br&gt;
This method:&lt;/p&gt;

&lt;p&gt;Reads the text from each document chunk.&lt;br&gt;
Sends the text to the embedding model.&lt;br&gt;
Receives a vector for each chunk.&lt;br&gt;
Stores the vector and document metadata in Pinecone.&lt;br&gt;
Step 5: Retrieve Information and Generate an Answer&lt;br&gt;
After ingestion is complete, we can ask questions.&lt;/p&gt;

&lt;p&gt;Become a Medium member&lt;br&gt;
Here is the retrieval script:&lt;/p&gt;

&lt;p&gt;from dotenv import load_dotenv&lt;br&gt;
from langchain_core.prompts import ChatPromptTemplate&lt;br&gt;
from langchain_openai import ChatOpenAI, OpenAIEmbeddings&lt;br&gt;
from langchain_pinecone import PineconeVectorStore&lt;br&gt;
load_dotenv()&lt;br&gt;
INDEX_NAME = "medium-blogs-embedding-index"&lt;br&gt;
EMBEDDING_MODEL = "text-embedding-3-small"&lt;br&gt;
EMBEDDING_DIMENSION = 512&lt;br&gt;
embeddings = OpenAIEmbeddings(&lt;br&gt;
    model=EMBEDDING_MODEL,&lt;br&gt;
    dimensions=EMBEDDING_DIMENSION,&lt;br&gt;
)&lt;/p&gt;

&lt;h1&gt;
  
  
  This was the model used in my original project.
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Replace it when necessary with a model available to your account.
&lt;/h1&gt;

&lt;p&gt;llm = ChatOpenAI(&lt;br&gt;
    model="gpt-4o-mini",&lt;br&gt;
    temperature=0,&lt;br&gt;
)&lt;br&gt;
vectorstore = PineconeVectorStore(&lt;br&gt;
    index_name=INDEX_NAME,&lt;br&gt;
    embedding=embeddings,&lt;br&gt;
)&lt;br&gt;
retriever = vectorstore.as_retriever(&lt;br&gt;
    search_kwargs={"k": 5}&lt;br&gt;
)&lt;br&gt;
prompt_template = ChatPromptTemplate.from_template(&lt;br&gt;
    """&lt;br&gt;
You are a helpful assistant.&lt;br&gt;
Answer the question using only the context provided below.&lt;br&gt;
If the answer is not present in the context, say:&lt;br&gt;
"I could not find that information in the provided document."&lt;br&gt;
Context:&lt;br&gt;
{context}&lt;br&gt;
Question:&lt;br&gt;
{question}&lt;br&gt;
Answer:&lt;br&gt;
"""&lt;br&gt;
)&lt;br&gt;
def format_documents(documents) -&amp;gt; str:&lt;br&gt;
    return "\n\n".join(&lt;br&gt;
        document.page_content for document in documents&lt;br&gt;
    )&lt;br&gt;
def answer_question(question: str) -&amp;gt; str:&lt;br&gt;
    documents = retriever.invoke(question)&lt;br&gt;
    context = format_documents(documents)&lt;br&gt;
    messages = prompt_template.format_messages(&lt;br&gt;
        context=context,&lt;br&gt;
        question=question,&lt;br&gt;
    )&lt;br&gt;
    response = llm.invoke(messages)&lt;br&gt;
    return response.content&lt;br&gt;
if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    user_question = input("Ask a question: ").strip()&lt;br&gt;
    if not user_question:&lt;br&gt;
        raise ValueError("The question cannot be empty.")&lt;br&gt;
    answer = answer_question(user_question)&lt;br&gt;
    print("\nAnswer:\n")&lt;br&gt;
    print(answer)&lt;br&gt;
Run it with:&lt;/p&gt;

&lt;p&gt;uv run python rag-gist/main.py&lt;br&gt;
The program asks for a question:&lt;/p&gt;

&lt;p&gt;Ask a question: What is the main idea of the document?&lt;br&gt;
It then searches Pinecone and sends the most relevant sections to the language model.&lt;/p&gt;

&lt;p&gt;Press enter or click to view image in full size&lt;/p&gt;

&lt;p&gt;Query for simple RAG System&lt;br&gt;
Caption: The application retrieved relevant document sections and used them to generate an answer.&lt;/p&gt;

&lt;p&gt;Why Use a Retriever?&lt;br&gt;
The vector store handles storage and similarity search.&lt;/p&gt;

&lt;p&gt;A retriever provides a simpler interface for requesting relevant documents:&lt;/p&gt;

&lt;p&gt;retriever = vectorstore.as_retriever(&lt;br&gt;
    search_kwargs={"k": 5}&lt;br&gt;
)&lt;br&gt;
The value k=5 means:&lt;/p&gt;

&lt;p&gt;Return the five document chunks that are most closely related to the question.&lt;/p&gt;

&lt;p&gt;When this line runs:&lt;/p&gt;

&lt;p&gt;documents = retriever.invoke(question)&lt;br&gt;
the application:&lt;/p&gt;

&lt;p&gt;Converts the question into an embedding,&lt;br&gt;
Searches Pinecone,&lt;br&gt;
Finds the closest vectors.&lt;br&gt;
Returns their original text.&lt;br&gt;
How the Prompt Reduces Unsupported Answers&lt;br&gt;
The prompt contains an important instruction:&lt;/p&gt;

&lt;p&gt;Answer the question using only the context provided below.&lt;br&gt;
It also tells the model what to do when the answer is missing:&lt;/p&gt;

&lt;p&gt;If the answer is not present in the context, say:&lt;br&gt;
"I could not find that information in the provided document."&lt;br&gt;
This does not guarantee perfect accuracy, but it gives the model a clear boundary.&lt;/p&gt;

&lt;p&gt;A RAG system should not only retrieve information. It should also tell the model how that information must be used.&lt;/p&gt;

&lt;p&gt;What Is a LangChain Runnable?&lt;br&gt;
LangChain uses a common interface called a Runnable.&lt;/p&gt;

&lt;p&gt;A runnable is something that accepts input and produces output.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;documents = retriever.invoke(question)&lt;br&gt;
and:&lt;/p&gt;

&lt;p&gt;response = llm.invoke(messages)&lt;br&gt;
Both the retriever and the language model support .invoke().&lt;/p&gt;

&lt;p&gt;That common interface makes it easier to connect prompts, retrievers, models, and custom functions into larger chains.&lt;/p&gt;

&lt;p&gt;Problems I Encountered&lt;br&gt;
The most useful part of building this project was understanding the errors.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Wrong Pinecone Index Name
The error said:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Index 'mediumblog' not found.&lt;br&gt;
Did you mean: medium-blogs-embedding-index&lt;br&gt;
The name in the Python script did not match the name in Pinecone.&lt;/p&gt;

&lt;p&gt;I fixed the constant:&lt;/p&gt;

&lt;p&gt;INDEX_NAME = "medium-blogs-embedding-index"&lt;br&gt;
A useful improvement is to keep shared settings in one configuration file so that ingestion and retrieval cannot accidentally use different index names.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vector Dimension Mismatch
I then received:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Vector dimension 1536 does not match&lt;br&gt;
the dimension of the index 512&lt;br&gt;
The Pinecone index expected vectors containing 512 values, while the application was sending vectors of a different size.&lt;/p&gt;

&lt;p&gt;I fixed it by explicitly setting:&lt;/p&gt;

&lt;p&gt;dimensions=512&lt;br&gt;
The same embedding model and dimension must be used during both ingestion and retrieval.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using the Wrong Constructor Parameter
I initially used:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;PineconeVectorStore(&lt;br&gt;
    index_name=INDEX_NAME,&lt;br&gt;
    embeddings=embeddings,&lt;br&gt;
)&lt;br&gt;
However, the constructor expected embedding, singular:&lt;/p&gt;

&lt;p&gt;PineconeVectorStore(&lt;br&gt;
    index_name=INDEX_NAME,&lt;br&gt;
    embedding=embeddings,&lt;br&gt;
)&lt;br&gt;
Current LangChain-Pinecone examples also initialize the vector store with an embedding object.&lt;/p&gt;

&lt;p&gt;This was a small naming difference, but it prevented the application from starting.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prompt Variable Mismatch
My prompt used this placeholder:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;{question}&lt;br&gt;
But the code passed:&lt;/p&gt;

&lt;p&gt;query=query&lt;br&gt;
LangChain raised:&lt;/p&gt;

&lt;p&gt;KeyError: 'question'&lt;br&gt;
The variable name passed to the template must exactly match the placeholder:&lt;/p&gt;

&lt;p&gt;messages = prompt_template.format_messages(&lt;br&gt;
    context=context,&lt;br&gt;
    question=query,&lt;br&gt;
)&lt;br&gt;
This error also reminded me to keep naming consistent throughout the application.&lt;/p&gt;

&lt;p&gt;What I Would Improve Next&lt;br&gt;
This project is a good learning version, but it is not yet a production-ready RAG system.&lt;/p&gt;

&lt;p&gt;My next improvements would be:&lt;/p&gt;

&lt;p&gt;Use a Better Text Splitter&lt;br&gt;
I would replace CharacterTextSplitter with RecursiveCharacterTextSplitter.&lt;/p&gt;

&lt;p&gt;It tries to keep paragraphs and sentences together instead of cutting the text only by character count.&lt;/p&gt;

&lt;p&gt;Add Chunk Overlap&lt;br&gt;
For example:&lt;/p&gt;

&lt;p&gt;chunk_size=1000&lt;br&gt;
chunk_overlap=150&lt;br&gt;
The overlap helps preserve information that appears near chunk boundaries.&lt;/p&gt;

&lt;p&gt;Prevent Duplicate Ingestion&lt;br&gt;
Running the ingestion script repeatedly can store the same content more than once.&lt;/p&gt;

&lt;p&gt;A production version should create stable document IDs and update existing records instead of always inserting new ones.&lt;/p&gt;

&lt;p&gt;Return Source Information&lt;br&gt;
The answer should show which chunks or source files were used.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;Source: mediumblog.txt, chunk 8&lt;br&gt;
This would make the application easier to trust and debug.&lt;/p&gt;

&lt;p&gt;Add a Relevance Threshold&lt;br&gt;
The application currently returns the top five chunks even when none of them is strongly related to the question.&lt;/p&gt;

&lt;p&gt;A similarity threshold could help reject unrelated results.&lt;/p&gt;

&lt;p&gt;Add Logging and Tracing&lt;br&gt;
Tracing tools can show:&lt;/p&gt;

&lt;p&gt;which question was asked&lt;br&gt;
which chunks were retrieved&lt;br&gt;
how long each step took&lt;br&gt;
how many tokens were used&lt;br&gt;
what answer was generated&lt;br&gt;
Create an Evaluation Set&lt;br&gt;
I would prepare a small collection of:&lt;/p&gt;

&lt;p&gt;test questions&lt;br&gt;
expected sources&lt;br&gt;
expected answer points&lt;br&gt;
This would make it easier to compare changes to chunk size, retrieval count, prompts, and embedding models.&lt;/p&gt;

&lt;p&gt;What I Learned&lt;br&gt;
Before building this project, RAG looked like one complicated AI feature.&lt;/p&gt;

&lt;p&gt;After implementing it manually, I understood that it is simply a pipeline:&lt;/p&gt;

&lt;p&gt;Documents become vectors.&lt;br&gt;
Questions become vectors.&lt;br&gt;
Vector search finds related text.&lt;br&gt;
The language model turns that text into an answer.&lt;br&gt;
The difficult part is not calling one magical RAG function.&lt;/p&gt;

&lt;p&gt;The important decisions are:&lt;/p&gt;

&lt;p&gt;how the document is divided,&lt;br&gt;
which embedding model is used&lt;br&gt;
whether vector dimensions match&lt;br&gt;
how many chunks are retrieved&lt;br&gt;
how irrelevant results are handled&lt;br&gt;
what instructions are given to the language model&lt;br&gt;
how sources are shown to the user&lt;br&gt;
One of the most useful lessons from this project was to inspect the retrieved chunks before changing the prompt.&lt;br&gt;
If the correct information is not retrieved, the language model cannot use it, no matter how well the prompt is written.&lt;br&gt;
Building each step separately made the architecture much easier to understand.&lt;/p&gt;

&lt;p&gt;Final Thoughts&lt;br&gt;
A small RAG application is a useful project for learning how modern AI applications work with external knowledge.&lt;/p&gt;

&lt;p&gt;The best way to learn RAG is to begin with one document, one question, and one successful retrieval.&lt;/p&gt;

&lt;p&gt;It teaches more than prompt writing. It introduces document processing, embeddings, vector search, retrieval, prompt design, configuration management, and debugging.&lt;/p&gt;

&lt;p&gt;The first version does not need to be perfect.&lt;/p&gt;

&lt;p&gt;Start with one document, one ingestion script, one retrieval script, and one question.&lt;/p&gt;

&lt;p&gt;Once the basic pipeline works reliably, improve one part at a time and observe how each change affects retrieval quality.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>openai</category>
      <category>rag</category>
    </item>
    <item>
      <title>Computed and Watchers in Vue: A Deep Dive</title>
      <dc:creator>Bidisha Das</dc:creator>
      <pubDate>Sun, 09 Nov 2025 10:12:51 +0000</pubDate>
      <link>https://dev.to/officialbidisha/computed-and-watchers-in-vue-1pfd</link>
      <guid>https://dev.to/officialbidisha/computed-and-watchers-in-vue-1pfd</guid>
      <description>&lt;p&gt;In Vue 2, &lt;code&gt;computed&lt;/code&gt; properties and &lt;code&gt;watch&lt;/code&gt; functions are key tools in the reactivity system. Understanding their internals and appropriate use cases is crucial to writing efficient, predictable applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Vue 2 Reactivity System (Brief Primer)
&lt;/h2&gt;

&lt;p&gt;Vue 2 uses &lt;strong&gt;getter/setter interception&lt;/strong&gt; via &lt;code&gt;Object.defineProperty&lt;/code&gt; to make data reactive. When a component renders or computes a value, Vue tracks which properties were accessed. If those properties change, Vue knows which components or functions to re-run.&lt;/p&gt;

&lt;p&gt;This tracking mechanism powers both &lt;code&gt;computed&lt;/code&gt; and &lt;code&gt;watch&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;computed&lt;/code&gt;: Lazy, Cached Derivations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Purpose
&lt;/h3&gt;

&lt;p&gt;To derive state from other reactive properties &lt;strong&gt;without side effects&lt;/strong&gt;, and cache the result &lt;strong&gt;until a dependency changes&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal Behavior
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lazily evaluated&lt;/strong&gt;: only recalculates when accessed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memoized&lt;/strong&gt;: tracks dependencies and only updates when they change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purity enforced&lt;/strong&gt;: should have no side effects or async logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prototype Note
&lt;/h3&gt;

&lt;p&gt;Computed properties are defined on the component’s prototype, so they don’t appear as own properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;computedProp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Arguments Are Not Allowed
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Not allowed&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to pass arguments, use a method instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;flag&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; 
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someDataProperty&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;otherVariable&lt;/span&gt; 
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someDataProperty&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example: Basic Sum
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Computed sum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Example: Product Price Calculation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;finalPrice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;basePrice&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taxRate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;discount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Example: Reducing Expression Length
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;deeplyNestedValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;submodule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deepValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simplifies access and ensures reactivity when store updates.&lt;/p&gt;

&lt;p&gt;Points to remember&lt;/p&gt;

&lt;p&gt;Try to avoid mutating computed property as much as possible. Instead of mutating the computed property, you should try to update the data field which triggers new computations and invokes the getter. &lt;/p&gt;

&lt;p&gt;A computed property behaves like a pure function: it always returns the same output for the same input, and it only re-evaluates when one of its reactive dependencies changes.&lt;/p&gt;

&lt;p&gt;In contrast, a method is a regular function that can be called any number of times—regardless of whether its dependencies have changed. It's not cached, doesn't need to be pure, and doesn't create any new reactive data on its own.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frl55g0gvpa2p35ilr8hj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frl55g0gvpa2p35ilr8hj.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;watch&lt;/code&gt;: Reactive Side Effects
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Purpose
&lt;/h3&gt;

&lt;p&gt;To &lt;strong&gt;observe changes&lt;/strong&gt; to specific reactive properties and trigger &lt;strong&gt;imperative code&lt;/strong&gt;, including side effects or async logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal Behavior
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eager&lt;/strong&gt;: runs handler when dependencies change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can be async&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supports &lt;code&gt;deep&lt;/code&gt; and &lt;code&gt;immediate&lt;/code&gt; options&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Arguments
&lt;/h3&gt;

&lt;p&gt;The handler receives the &lt;strong&gt;new and old value&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;myVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;changed from&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldVal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;to&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Example: Async API on Property Change
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;immediate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Example: Debounced Search API
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;searchQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newQuery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_searchTimeout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_searchTimeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Example: Reacting to Deep Object
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Settings updated:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;deep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Example: Routing on Condition
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;somethingSelected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/next-step&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Example: Fetch Data on Filter Change
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newFilters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadTableData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newFilters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;deep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;loadTableData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/data?&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tableData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Comparison Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;code&gt;computed&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;watch&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Trigger&lt;/td&gt;
&lt;td&gt;Lazy (on access)&lt;/td&gt;
&lt;td&gt;Eager (on mutation)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Purpose&lt;/td&gt;
&lt;td&gt;Derived value&lt;/td&gt;
&lt;td&gt;Side effects / async&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caching&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Async Support&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Side Effects&lt;/td&gt;
&lt;td&gt;No (should be pure)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deep/Nested Support&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (via &lt;code&gt;deep: true&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arguments&lt;/td&gt;
&lt;td&gt;❌ Not allowed&lt;/td&gt;
&lt;td&gt;✅ newVal, oldVal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  React Equivalents
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;computed&lt;/code&gt; → &lt;code&gt;useMemo&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Computing sum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;watch&lt;/code&gt; → &lt;code&gt;useEffect&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;setUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;loadUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deep Watch in React (manual)
&lt;/h3&gt;

&lt;p&gt;React doesn't support deep watching natively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Settings changed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  When to Use What
&lt;/h2&gt;

&lt;p&gt;Adapted from Flavio Copes' best practices:&lt;/p&gt;

&lt;h3&gt;
  
  
  Use &lt;code&gt;methods&lt;/code&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To respond to DOM events (e.g., &lt;code&gt;@click&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;When you need to pass arguments&lt;/li&gt;
&lt;li&gt;To call imperative logic on user action&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use &lt;code&gt;computed&lt;/code&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To create derived state from reactive sources&lt;/li&gt;
&lt;li&gt;When using nested data in the template&lt;/li&gt;
&lt;li&gt;When a value should update reactively without manual tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use &lt;code&gt;watch&lt;/code&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To trigger side effects (e.g., route change, fetch data)&lt;/li&gt;
&lt;li&gt;To observe prop changes&lt;/li&gt;
&lt;li&gt;To respond to a single property reaching a specific value&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Anti-Patterns
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Using &lt;code&gt;watch&lt;/code&gt; for derivation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nf"&gt;b&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ❌ Side effects in &lt;code&gt;computed&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ❌ side effect&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use &lt;code&gt;computed&lt;/code&gt;&lt;/strong&gt; for pure derivations that should be cached.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use &lt;code&gt;watch&lt;/code&gt;&lt;/strong&gt; for executing logic when data changes, especially async effects.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In &lt;strong&gt;React&lt;/strong&gt;, replicate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;computed&lt;/code&gt; with &lt;code&gt;useMemo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;watch&lt;/code&gt; with &lt;code&gt;useEffect&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Vue 2's split between &lt;code&gt;computed&lt;/code&gt; and &lt;code&gt;watch&lt;/code&gt; promotes clear separation of &lt;strong&gt;declarative derivation&lt;/strong&gt; vs &lt;strong&gt;imperative side effects&lt;/strong&gt;, a pattern React replicates using different primitives.&lt;/p&gt;




&lt;p&gt;Need live examples, benchmarking, or async control patterns (e.g., cancellation with &lt;code&gt;watch&lt;/code&gt;)? Ask and I can break that down next.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>frontend</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Port and Adapter Architecture in Real Life (with Java)</title>
      <dc:creator>Bidisha Das</dc:creator>
      <pubDate>Wed, 25 Jun 2025 09:29:26 +0000</pubDate>
      <link>https://dev.to/officialbidisha/port-and-adapter-architecture-in-real-life-with-java-4cm7</link>
      <guid>https://dev.to/officialbidisha/port-and-adapter-architecture-in-real-life-with-java-4cm7</guid>
      <description>&lt;p&gt;Modern software development often faces one major hurdle: tight coupling. Whether you're swapping out a database, switching from REST to GraphQL, or integrating a new third-party service, making changes without breaking the core business logic can feel like performing surgery with a sledgehammer.&lt;/p&gt;

&lt;p&gt;Port and Adapter Architecture, also known as Hexagonal Architecture, was created to solve this exact problem. It puts the core logic at the center and treats all external dependencies—databases, UIs, APIs—as plug-and-play accessories.&lt;/p&gt;

&lt;p&gt;In this blog post, we’ll explore this architecture with an intuitive analogy, compare it to traditional layered architecture, and implement a Task Manager App in Java that retrieves tasks for users.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Port and Adapter Architecture?
&lt;/h2&gt;

&lt;p&gt;Think of the application core as the brain of your app. It defines what the app does, not how it's done. To interface with the messy outside world, it uses:&lt;/p&gt;

&lt;p&gt;Ports: Abstract interfaces that define how external actors interact with the app. Think of ports like the USB ports on your laptop—they stay the same regardless of the device you plug in.&lt;/p&gt;

&lt;p&gt;Adapters: Concrete implementations that plug into ports and use specific technologies. Like USB cables, you use different ones depending on the kind of device (application or service) you're connecting.&lt;/p&gt;

&lt;p&gt;Configurator: The glue that wires everything together at runtime.&lt;/p&gt;

&lt;p&gt;Even if your cable (adapter) changes, your port remains the same. It's this stability that makes the architecture so flexible and powerful.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏠 Real-World Analogy: Home Appliances
&lt;/h2&gt;

&lt;p&gt;House (Core) = Your application's business logic&lt;/p&gt;

&lt;p&gt;Sockets (Ports) = Interfaces that define what’s possible&lt;/p&gt;

&lt;p&gt;Appliances (Adapters) = Implementations using those sockets (e.g., toaster, TV)&lt;/p&gt;

&lt;p&gt;Electrician (Configurator) = Connects the right appliance to the right socket&lt;/p&gt;

&lt;p&gt;Need to switch from a toaster to a microwave? You don’t rebuild the house—you just plug in a new appliance.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔁 Compared to Layered Architecture
&lt;/h2&gt;

&lt;p&gt;Layered architecture often leads to unnecessary and tight coupling between layers. Typically, applications follow a flow like:&lt;/p&gt;

&lt;p&gt;UI → Service → Repository → DB&lt;/p&gt;

&lt;p&gt;However, in many real-world cases, the boundaries blur. The business logic starts depending directly on the database entities and infrastructure-specific components. For example, ORM entities like JPA are often available throughout the service and UI layers, exposing technical details such as lazy loading and transaction management to places they shouldn't be.&lt;/p&gt;

&lt;p&gt;This not only leads to subtle bugs (like uninitialized collections being accessed from the UI) but also makes it difficult to test business logic in isolation—because it ends up entangled with database access logic.&lt;/p&gt;

&lt;p&gt;Worse still, updating infrastructure components—like changing the ORM framework or database version—requires changes across all layers, which becomes a bottleneck and is often neglected due to the high cost.&lt;/p&gt;

&lt;p&gt;In contrast, Hexagonal Architecture flips this structure. The application core depends only on ports (interfaces). External systems—whether databases, REST APIs, or UIs—connect via adapters. This keeps the core pure and decoupled from implementation details, enabling isolated testing and easier tech upgrades.. The app core only talks to ports. Everything else plugs in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Our Example: Task Manager App
&lt;/h2&gt;

&lt;p&gt;Use Case: "Fetch all pending tasks for a user"&lt;/p&gt;

&lt;p&gt;We’ll build it using Port and Adapter architecture. Components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Port (interface)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adapter (simulated database)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application Service (core logic)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configurator (wiring)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Client (runner)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 1: Define the Port
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface TaskRetrievalPort {
    List&amp;lt;Task&amp;gt; getPendingTasksForUser(String userId);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This interface represents a contract. The service layer only depends on this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Create the Adapter (Simulating a DB)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class InMemoryTaskAdapter implements TaskRetrievalPort {
    private final Map&amp;lt;String, List&amp;lt;Task&amp;gt;&amp;gt; db = new HashMap&amp;lt;&amp;gt;();

    public InMemoryTaskAdapter() {
        db.put("user1", List.of(
            new Task("1", "Buy milk", true),
            new Task("2", "Read book", false)
        ));
    }

    @Override
    public List&amp;lt;Task&amp;gt; getPendingTasksForUser(String userId) {
        return db.getOrDefault(userId, List.of()).stream()
                 .filter(task -&amp;gt; !task.isCompleted())
                 .collect(Collectors.toList());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Application Core Service
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class TaskService {
    private final TaskRetrievalPort taskPort;

    public TaskService(TaskRetrievalPort taskPort) {
        this.taskPort = taskPort;
    }

    public List&amp;lt;Task&amp;gt; getUserPendingTasks(String userId) {
        return taskPort.getPendingTasksForUser(userId);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Configurator
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class TaskServiceConfigurator {
    public static TaskService createDefaultService() {
        TaskRetrievalPort adapter = new InMemoryTaskAdapter();
        return new TaskService(adapter);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Task Model + Main Client
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Task {
    private final String id;
    private final String description;
    private final boolean completed;

    public Task(String id, String description, boolean completed) {
        this.id = id;
        this.description = description;
        this.completed = completed;
    }

    public boolean isCompleted() { return completed; }
    public String getDescription() { return description; }
}

public class Main {
    public static void main(String[] args) {
        TaskService service = TaskServiceConfigurator.createDefaultService();
        List&amp;lt;Task&amp;gt; tasks = service.getUserPendingTasks("user1");

        tasks.forEach(task -&amp;gt; System.out.println("Pending: " + task.getDescription()));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ✅ Benefits in Practice
&lt;/h2&gt;

&lt;p&gt;Want to add a real DB later? Just create a new adapter.&lt;br&gt;
Need to expose tasks via REST? Add a REST adapter.&lt;br&gt;
Writing tests? Mock the port interface.&lt;/p&gt;

&lt;p&gt;No changes to TaskService are needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  📐 Testing Support
&lt;/h2&gt;

&lt;p&gt;Hexagonal architecture makes testing clean and painless:&lt;/p&gt;

&lt;p&gt;Unit tests talk to primary ports.&lt;/p&gt;

&lt;p&gt;Mocks can replace secondary ports (e.g., database or notification systems).&lt;/p&gt;

&lt;p&gt;Adapters can be tested separately with stubs or integration tools like TestContainers.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Port and Adapter architecture doesn’t just help you write cleaner code—it empowers you to:&lt;/p&gt;

&lt;p&gt;Delay infrastructure decisions&lt;br&gt;
Embrace change confidently&lt;br&gt;
Build with clarity and testability&lt;/p&gt;

&lt;p&gt;Start small: wrap your use cases in interfaces, implement them with adapters, and connect them using a configurator. It’s a mindset shift—but one that pays off in the long run.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>designpatterns</category>
      <category>java</category>
    </item>
    <item>
      <title>Facebook System Design Frontend</title>
      <dc:creator>Bidisha Das</dc:creator>
      <pubDate>Sun, 23 Jun 2024 19:58:54 +0000</pubDate>
      <link>https://dev.to/officialbidisha/facebook-system-design-frontend-3i0j</link>
      <guid>https://dev.to/officialbidisha/facebook-system-design-frontend-3i0j</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tqbj8ggfr9putdz8vix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tqbj8ggfr9putdz8vix.png" alt=" " width="800" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Concurrency Limit</title>
      <dc:creator>Bidisha Das</dc:creator>
      <pubDate>Thu, 30 May 2024 16:54:19 +0000</pubDate>
      <link>https://dev.to/officialbidisha/concurrency-limit-1ajg</link>
      <guid>https://dev.to/officialbidisha/concurrency-limit-1ajg</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const CONCURRENCY_LIMIT = 3

function asyncTaskRunner(tasks) {
 const results = new Array(tasks.length).fill(0)
 const totalTasks = tasks.length
 let currentTaskIndex = 0
const runner = (resolve) =&amp;gt; {
   if (!Array.isArray(tasks)) {
     throw new Error("tasks must be Array");
   }
   let taskQueue = []
   const runNext = async () =&amp;gt; {
     if (taskQueue.length === 0 &amp;amp;&amp;amp; currentTaskIndex === totalTasks) {
       resolve(results)
       return
     }

     if (taskQueue.length &amp;gt;= CONCURRENCY_LIMIT || tasks.length === 0) {
       return
     }


     const taskIndex = currentTaskIndex;
     currentTaskIndex += 1

     const task = tasks.shift()
     console.log('scheduling task ', taskIndex)
     taskQueue.push(task)

     task()
       .then(result =&amp;gt; {
         console.log('finished task: ', taskIndex)
         results[taskIndex] = result
         taskQueue = taskQueue.filter((t =&amp;gt; t !== task))
         runNext()
       })
   }
   for (let i = 0 ; i &amp;lt; CONCURRENCY_LIMIT; i++) {
     if (tasks.length === 0) {
       break
     }


     const taskIndex = currentTaskIndex;
     currentTaskIndex += 1


     const task = tasks.shift()
     console.log('scheduling task ', taskIndex)
     taskQueue.push(task)


     task()
       .then(result =&amp;gt; {
         console.log('finished task: ', taskIndex)
         results[taskIndex] = result
         taskQueue = taskQueue.filter((t =&amp;gt; t !== task))
         runNext()
       })
   }
 };
 return new Promise((res) =&amp;gt; runner(res));
}


const t1 = () =&amp;gt; new Promise(res =&amp;gt; setTimeout(() =&amp;gt; res('t1'), 3000))
const t2 = () =&amp;gt; new Promise(res =&amp;gt; setTimeout(() =&amp;gt; res('t2'), 200))
const t3 = () =&amp;gt; new Promise(res =&amp;gt; setTimeout(() =&amp;gt; res('t3'), 1500))
const t4 = () =&amp;gt; new Promise(res =&amp;gt; setTimeout(() =&amp;gt; res('t4'), 5000))
const t5 = () =&amp;gt; new Promise(res =&amp;gt; setTimeout(() =&amp;gt; res('t5'), 4000))
const t6 = () =&amp;gt; new Promise(res =&amp;gt; setTimeout(() =&amp;gt; res('t6'), 1000))


const tasks = [t1, t2, t3, t4, t5, t6]


asyncTaskRunner(tasks)
 .then(console.log)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Creating Async Task Runner with Concurrency in JavaScript</title>
      <dc:creator>Bidisha Das</dc:creator>
      <pubDate>Tue, 29 Nov 2022 19:46:09 +0000</pubDate>
      <link>https://dev.to/officialbidisha/creating-async-task-runner-with-concurrency-in-javascript-49j9</link>
      <guid>https://dev.to/officialbidisha/creating-async-task-runner-with-concurrency-in-javascript-49j9</guid>
      <description>&lt;p&gt;Let us consider we need to create an aync task runner in javascript with the following constraint:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The task runner should have a set of tasks that will be pushed to it,&lt;/li&gt;
&lt;li&gt;Each of these tasks will be some async operation,&lt;/li&gt;
&lt;li&gt;The task runner should also ensure that at a single point of time only a given number of tasks can perform, and other tasks keep on waiting unless their turn comes. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's code out the solution first&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Runner{
      constructor(concurrency=1){
          this.concurrency = concurrency;
          this.waitList = [];
          this.count = 0;
          this.currentQ = [];
      }
      push(task){
         this.waitList.push(task);
         this.run();
      }
      run(){
         let current = this;
         if(this.count&amp;lt;this.concurrency){
            this.count++;
            if(this.waitList.length&amp;gt;0){
               let task = this.waitList.shift();
               let id = task.id;
               this.currentQueue.push(id);
               this.showRunningTasks();
               let done = function(){ 
       this.currentQueue.splice(this.currentQueue.indexOf(id),1);
                  this.showRunningTasks();
                  this.count = this.count - 1;
                  this.run();
               }.bind(current);
               task.task(done);
            }
         }
      }

      showRunningTasks(){
         let existingQueue = this.currentQueue.join(", ");
         document.getElementId("running").innerHTML = existingQueue;
      }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4vqrjk2rxjkx1j9bhrz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4vqrjk2rxjkx1j9bhrz.gif" alt=" " width="515" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's understand this piece of code line by line. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Initially we pass the &lt;code&gt;concurrency&lt;/code&gt;flag indicating how many tasks can run concurrently. The &lt;code&gt;waitList&lt;/code&gt; is used for making a wait list of tasks, which will wait unless the queue referred to as &lt;code&gt;currentQueue&lt;/code&gt; is empty. The &lt;code&gt;count&lt;/code&gt; variable is initialised to count the number of concurrent tasks at a moment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;push&lt;/code&gt; method is used to push a task to &lt;code&gt;waitList&lt;/code&gt;, and we then execute the run method.This simply indicates that the tasks need to be run if the queue is empty&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The run method is interesting. First it preserves the context of the task by the virtue of first line denoted as &lt;code&gt;let current = this&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we check for the concurrency and if the waitList has elements, we simply,&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;  push the task id to the currentQueue, &lt;/li&gt;
&lt;li&gt; display the current running tasks via the method &lt;code&gt;showRunningTasks&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;  in the inner &lt;code&gt;done&lt;/code&gt;method, which will be taken as a callback 
in tasks, we simply &lt;strong&gt;remove the task with the id from current&lt;br&gt;
queue&lt;/strong&gt;, &lt;strong&gt;reduce the count to reduce the total number of concurrent tasks&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt; In the end, we recursively call the run() method to run the 
current function. Note, here the context remains same. &lt;/li&gt;
&lt;li&gt;Lastly we bind this function to the current context. &lt;/li&gt;
&lt;li&gt;We pass this function to task.task function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's now see how this method can be used&lt;/p&gt;

&lt;p&gt;Use the following code snippet to see the result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let runner = new Runner(3);
let task1 = {
  id: 1,
  task: function(done) {
    setTimeout(function() {
      console.log("Task 1");
      done();
    }, 3000)
  }
}

let task2 = {
  id: 2,
  task: function(done) {
    setTimeout(function() {
      console.log("Task 2");
      done();
    }, 5000)
  }
}

let task3 = {
  id: 3,
  task: function(done) {
    setTimeout(function() {
      console.log("Task 3");
      done();
    }, 4000)
  }
}

let task4 = {
  id: 4,
  task: function(done) {
    setTimeout(function() {
      console.log("Task 4");
      done();
    }, 9000)
  }
}

runner.push(task1);
runner.push(task2);
runner.push(task3);
runner.push(task4);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You will see the result on the screen as Task 1, Task 3, Task 2, Task 4&lt;/strong&gt;, which is expected. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>learning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Compound Components Pattern in React</title>
      <dc:creator>Bidisha Das</dc:creator>
      <pubDate>Tue, 28 Jun 2022 17:12:45 +0000</pubDate>
      <link>https://dev.to/officialbidisha/compound-components-pattern-in-react-35dp</link>
      <guid>https://dev.to/officialbidisha/compound-components-pattern-in-react-35dp</guid>
      <description>&lt;p&gt;During development, we face some design patterns in React. Compound Components is one of the most important and frequently used Design Pattern in React. Let us create a Expandable Accordion component using React. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compound Components are components that are made up of two or more components which cannot be used without it's parent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A select box is an example of it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52b7mw9w9czbk7zvy71x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52b7mw9w9czbk7zvy71x.jpg" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Intially, we set up the Expandable component. Here is the code that goes along with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, {createContext} from React;
const ExpandableContext = createContext();
const {Provider} = ExpandableContext;

const Expandable = ({children}) =&amp;gt; {
    return &amp;lt;Provider&amp;gt;{children}&amp;lt;/Provider&amp;gt;
}

export default Expandable;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following things are happening here&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ExpdandableContext is created,&lt;/li&gt;
&lt;li&gt;The Provider is desctructured from the ExpandableContext&lt;/li&gt;
&lt;li&gt;In the end, we are just creating an Expandable Component and returning the JSX with the Provider that displays the children passed to the Expandable component&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now we have to introduce state for the expanded accordion and even create a toggle function for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Expandable = ({children}) =&amp;gt; {

    /**
     * State to update the expanded behaviour
     */
    const [expanded, setExpanded] = useState(false);

    /**
     * Method for toggling the expanded state
     */
    const toggle = setExpanded(prevExpanded =&amp;gt; !prevExpanded);

    return &amp;lt;Provider&amp;gt;{children}&amp;lt;/Provider&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the toggle callback function will be invoked by the expandable header and it shouldn't change every time or re-render. Hence, we can memoize the callback as follows. &lt;/p&gt;

&lt;p&gt;After this, we need to pass these - toggle function and expanded to the provider. Hence we write this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const value = { expanded, toggle }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and to prevent the re-rendering of value every time, we use useMemo for preserving the object on every render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const value = useMemo(()=&amp;gt; {expanded, toggle}, [expnded, toggle]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Providing flexibility to the external user to provide custom functionality after expansion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At times, it will be the requirement to provide custom functionality to the user after the accordion is expanded. In this case we can follow the below pattern. &lt;/p&gt;

&lt;p&gt;For class components we can do this using a callback, however for functional components we need to do this with useeffect and run this only when the functional component has already been mounted (it should not run when the component is mounted every time).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     * Check for mounting
     */
    const componentJustMounted = useRef(true);

    /**
     * Function to call when the expanded state is altered tp true, 
     * that is when the expansion happens. 
     */
    useEffect(()=&amp;gt; {
        if(!componentJustMounted.current){
            onExpand(expanded);
        }
        componentJustMounted.current = false
    }, [expanded]) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using a useRef as it will return a reference which will be preserved during render cycles. Initially it is set to true. We only make it false when the callback is executed with the expanded prop passed to it. &lt;/p&gt;

&lt;p&gt;Hence the whole component Expandable.js looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, {createContext, useState, useCallback, useRef, useEffect} from 'react';
const ExpandableContext = createContext();
const {Provider} = ExpandableContext;

const Expandable = ({children}) =&amp;gt; {

    /**
     * State to update the expanded behaviour
     */
    const [expanded, setExpanded] = useState(false);

    /**
     * Check for mounting
     */
    const componentJustMounted = useRef(true);

    /**
     * Function to call when the expanded state is altered tp true, 
     * that is when the expansion happens. 
     */
    useEffect(()=&amp;gt; {

        if(!componentJustMounted.current){
            onExpand(expanded);
        }
        componentJustMounted.current = false
    }, [expanded, onExpand])

    /**
     * Method for toggling the expanded state
     */
    const toggle = useCallback(() =&amp;gt; 
        setExpanded(prevExpanded =&amp;gt; !prevExpanded), []
    );

    const value = useMemo(()=&amp;gt; {expanded, toggle}, [expanded, toggle])

    return &amp;lt;Provider value={value}&amp;gt;{children}&amp;lt;/Provider&amp;gt;
}

export default Expandable;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Building Child Components&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The three components of the body, header and icon are as follows. &lt;/p&gt;

&lt;p&gt;Header.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useContext } from 'react'
import { ExpandableContext } from './Expandable'

const Header = ({children}) =&amp;gt; {
  const { toggle } = useContext(ExpandableContext)
  return &amp;lt;div onClick={toggle}&amp;gt;{children}&amp;lt;/div&amp;gt;
}
export default Header; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we just try and access the toggle and on click we toggle the body on click of the div. This is the by default feature of accordion.&lt;/p&gt;

&lt;p&gt;For Body, &lt;/p&gt;

&lt;p&gt;Body.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useContext } from 'react'
import { ExpandableContext } from './Expandable'

const Body = ({ children }) =&amp;gt; {
  const { expanded } = useContext(ExpandableContext)
  return expanded ? children : null
}
export default Body
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the body, we check if the expanded property is true or not. If it is true, we set the body to the props.children passes to it, otherwise we return null (since the body is not expanded). &lt;/p&gt;

&lt;p&gt;For icon, we can use Icon.js which looks like this:&lt;/p&gt;

&lt;p&gt;Icon.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Icon.js
import { useContext } from 'react'
import { ExpandableContext } from './Expandable'

const Icon = () =&amp;gt; {
  const { expanded } = useContext(ExpandableContext)
  return expanded ? '-' : '+'
}
export default Icon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For expanded body, we show a - sign and for contracted body, we show, +. &lt;/p&gt;

&lt;p&gt;After adding these logics, let us add just the styles in the each of these elements and finally the components look like this. &lt;/p&gt;

&lt;p&gt;Expandable.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, {
  createContext,
  useState,
  useCallback,
  useRef,
  useEffect,
  useMemo,
} from "react";
export const ExpandableContext = createContext();
const { Provider } = ExpandableContext;

const Expandable = ({ onExpand, children, className = "", ...otherProps }) =&amp;gt; {
  const combinedClasses = ["Expandable", className].filter(Boolean).join("");

  /**
   * State to update the expanded behaviour
   */
  const [expanded, setExpanded] = useState(false);

  /**
   * Check for mounting
   */
  const componentJustMounted = useRef(true);

  /**
   * Method for toggling the expanded state
   */
  const toggle = useCallback(
    () =&amp;gt; setExpanded((prevExpanded) =&amp;gt; !prevExpanded),
    []
  );

  /**
   * Function to call when the expanded state is altered tp true,
   * that is when the expansion happens.
   */
  useEffect(() =&amp;gt; {
    if (!componentJustMounted.current) {
      onExpand(expanded);
    }
    componentJustMounted.current = false;
  }, [expanded, onExpand]);

  const value = useMemo(() =&amp;gt; ({ expanded, toggle }), [expanded, toggle]);

  return (
    &amp;lt;Provider value={value}&amp;gt;
      &amp;lt;div className={combinedClasses} {...otherProps}&amp;gt;{children}&amp;lt;/div&amp;gt;
    &amp;lt;/Provider&amp;gt;
  );
};
export default Expandable;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Body.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Body.js
import './Body.css'
import { useContext } from 'react'
import { ExpandableContext } from './Expandable'

const Body = ({ children , className='',... otherProps}) =&amp;gt; {
  const { expanded } = useContext(ExpandableContext);
  const combinedClassName = ['Expandable-panel', className].filter(Boolean).join('');
  return expanded ? 
  &amp;lt;div className ={combinedClassName} {...otherProps} &amp;gt;{children}&amp;lt;/div&amp;gt; : null
}
export default Body
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Header.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useContext } from 'react'
import { ExpandableContext } from './Expandable'
import './Header.css';
const Header = ({className='', children, ...otherProps}) =&amp;gt; {

  const combinedClassName = ['Expandable-trigger',className].filter(Boolean).join('');

  const { toggle } = useContext(ExpandableContext)
  return &amp;lt;button className={combinedClassName} {...otherProps}
  onClick={toggle}&amp;gt;{children}&amp;lt;/button&amp;gt;
}
export default Header;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Icon.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useContext } from 'react'
import { ExpandableContext } from './Expandable'

const Icon = ({ className='', ...otherProps}) =&amp;gt; {
  const { expanded } = useContext(ExpandableContext);
  const combinedClassName = ['Expandable-icon', className].join('');
  return &amp;lt;span className={combinedClassName} {...otherProps}&amp;gt;{expanded ? '-' : '+'}&amp;lt;/span&amp;gt;
}
export default Icon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can view its behaviour at &lt;a href="https://officialbidisha.github.io/exapandable-app/" rel="noopener noreferrer"&gt;https://officialbidisha.github.io/exapandable-app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and the github code is available at &lt;a href="https://github.com/officialbidisha/exapandable-app" rel="noopener noreferrer"&gt;https://github.com/officialbidisha/exapandable-app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how compound components work. We cannot use the Expandable component without the Header, Icon and Body and vice versa. We have successfully learnt a design pattern now. &lt;/p&gt;

&lt;p&gt;Happy learning!&lt;/p&gt;

</description>
      <category>react</category>
      <category>designpattern</category>
      <category>compound</category>
      <category>components</category>
    </item>
    <item>
      <title>React 18 - New Features &amp; Improvement Strategies</title>
      <dc:creator>Bidisha Das</dc:creator>
      <pubDate>Sun, 17 Apr 2022 22:45:22 +0000</pubDate>
      <link>https://dev.to/officialbidisha/react-18-to-the-rescue-38g3</link>
      <guid>https://dev.to/officialbidisha/react-18-to-the-rescue-38g3</guid>
      <description>&lt;p&gt;On March 8th, the React team released the React 18 RC(Release Candidate). The latest release has brought a number of new features that would transform the coding pattern in a number of application. It brings along with it, a couple of performance improvements which I will be covering in this blog. &lt;/p&gt;

&lt;h3&gt;
  
  
  Concurrency
&lt;/h3&gt;

&lt;p&gt;Concurrency is a property of systems where several processes are executing at the same time, and may or may not interact with each other. Too complex? Let's break it down. Let's say there is a race that is being conducted. Now, concurrency is how many people are running for a single race in a parallel track. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8umsaxl8dv69xadwn1e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8umsaxl8dv69xadwn1e.jpg" alt="Concurrency" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Concurrency is a new feature that React 18 has introduced. It is a new behind-the-scene mechanism that enables React to &lt;strong&gt;prepare multiple versions of the UI at the same time&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;In this mechanism, unlike previous cases, React may start the rendering, pause in middle for some critical task and resume rendering again. The only thing to keep in mind is that it may also abandon in process render altogether. React guarantees that the UI appears consistent even though the render is interrupted. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This gives the capability of React to prepare screens in the background - without blocking the new thread!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Suspense for Server Side Rendering
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9190smf7ojw3vbjor3rd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9190smf7ojw3vbjor3rd.png" alt="Suspense in Server Side Rendering" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;React has brought forth the feature of Suspense in Server side rendering frameworks like Next.js, Relay, Hydrogen or Remix. React 18 introduces:&lt;br&gt;
&lt;strong&gt;Code splitting on the server&lt;/strong&gt; with suspense, and&lt;br&gt;
&lt;strong&gt;Streaming rendering on the server&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatic Batching
&lt;/h2&gt;

&lt;p&gt;Batching is the phenomenon via which React groups multiple state updates into a single re-render for better performance optimisation. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fheg1wl20xnkv9hbncw3t.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fheg1wl20xnkv9hbncw3t.gif" alt="Batching" width="748" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Previous to React 18, batch updates were performed for react-based event handlers. However for &lt;strong&gt;promises, setTimeouts, native event handlers or any other events,&lt;/strong&gt; batch updates were not performed. React 18 performs automatic batch updates for the above mentioned cases too. &lt;/p&gt;

&lt;p&gt;Let's understand this using a code. &lt;/p&gt;

&lt;pre&gt;setTimeout(() =&amp;gt; {
  setCount(count =&amp;gt; count + 1);
  setFlag(flag =&amp;gt; !flag);
  // React will only re-render once at the end (that's batching!)
}, 1000);
&lt;/pre&gt;

&lt;p&gt;Identically, the above code behaves the same as this:&lt;/p&gt;

&lt;pre&gt;fetch(/*...*/).then(() =&amp;gt; {
  setCount(counter =&amp;gt; counter + 1);
  setFlag(flag =&amp;gt; !flag);
  // React will only re-render once at the end (that's batching!)
})
&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;In case, you don't want to batch, you can use &lt;code&gt;ReactDOM.flushSync()&lt;/code&gt;&lt;/em&gt; . Let's understand with a bit of code&lt;/p&gt;

&lt;pre&gt;import { flushSync } from 'react-dom'; // Note: react-dom, not react

function handleFlushesClick() {
  flushSync(() =&amp;gt; {
    setCounter(counter =&amp;gt; counter + 1);
  });
  // React has updated the DOM by now
  flushSync(() =&amp;gt; {
    setFlag(flag =&amp;gt; !flag);
  });
  // React has updated the DOM by now
}
&lt;/pre&gt;

&lt;h2&gt;
  
  
  Transitions
&lt;/h2&gt;

&lt;p&gt;This feature distinguishes urgent vs non-urgent updates. An urgent update is one which needs immediate response. Urgent updates include actions like clicking, pressing, typing - things that require immediate response or where the &lt;em&gt;user expects the UI to respond immediately.&lt;/em&gt; &lt;br&gt;
&lt;strong&gt;No intermediate values are to be displayed on screen.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fih0bbg78vj461sob1ze5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fih0bbg78vj461sob1ze5.gif" alt="Transition example" width="560" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  A real life example
&lt;/h4&gt;

&lt;p&gt;Considering a real life example, let's think of a debounced typeahead. Now, while you type in the input, you expect the input box to reflect the values typed. However, do you expect the result to appear immediately? No right! It will debounce and then you get result. So , there is some transition time from the time you type your input till the time you get your suggestion. This time frame will be used for transition. &lt;/p&gt;

&lt;p&gt;Typically, for best user experience, a single user input should result in both urgent and non-urgent update. &lt;/p&gt;

&lt;pre&gt;import {startTransition} from 'react';

// Urgent: Show what was typed
    setInputValue(input);`

// Mark any state updates inside as transitions
  startTransition(() =&amp;gt; {
     // Transition: Show the autosuggestion based on the input 
        value
      setSearchQuery(input);
});
&lt;/pre&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbv88pvre4abh8796em8b.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbv88pvre4abh8796em8b.gif" alt="Search bar" width="600" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Another real-time example
&lt;/h4&gt;

&lt;pre&gt;const [isPending, startTransition] = useTransition()
&lt;/pre&gt;

&lt;p&gt;Here the useTransition hook has 2 parameters that is destructured. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;isPending&lt;/code&gt; : to denote if the UI update is still in transition state&lt;/p&gt;

&lt;p&gt;&lt;code&gt;startTransition&lt;/code&gt;: A function that executes code for transactions. &lt;/p&gt;

&lt;pre&gt;function handleClick() {
   startTransition(() =&amp;gt; {
     setTab('comments');
   });
}
&lt;/pre&gt;

&lt;p&gt;This function gets called when you want to switch from Photos tab to Comments tab.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;}&amp;gt;&lt;br&gt;
     &lt;/p&gt;
&lt;br&gt;
        {tab === 'photos' ?  : }&lt;br&gt;
     &lt;br&gt;
  

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;During the transition phase, while the new UI is being prepared by React, the tab with the Photos UI will be now shown to the user with 80% opacity to give a smooth view of transition.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Strict Mode in React
&lt;/h2&gt;

&lt;p&gt;The Strict Mode in development server brings forth a couple of interesting changes in React 18. This mode essentially provides out-of-box performance for React. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The series of events during mounting now:&lt;/p&gt;

&lt;p&gt;I. React mounts the component.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Layout effects are created.&lt;/li&gt;
&lt;li&gt;Effects are created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;II. React simulates unmounting the component.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Layout effects are destroyed.&lt;/li&gt;
&lt;li&gt;Effects are destroyed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;III. React simulates mounting the component with the previous state.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Layout effects are created.&lt;/li&gt;
&lt;li&gt;Effects are created.`&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During unmounting, the following events occur&lt;/p&gt;

&lt;p&gt;I. Layout effects are destroyed and Effect effects are destroyed. &lt;/p&gt;

&lt;h2&gt;
  
  
  New Hooks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F321rzz9e5sindiakqy9y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F321rzz9e5sindiakqy9y.png" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  a. useId
&lt;/h4&gt;

&lt;p&gt;useId is a new hook for generating** unique IDs on both the client and server*&lt;em&gt;, while avoiding hydration mismatches. This generates an **unique string containing : which does not collide with css selectors and &lt;code&gt;querySelectorAll&lt;/code&gt;&lt;/em&gt;*&lt;/p&gt;

&lt;p&gt;You can also use userId with identifierPrefix in order to prevent collision in multi-root applications. For multiple IDs in the same component, append a suffix using the same id.&lt;/p&gt;

&lt;h4&gt;
  
  
  b. useDeferredValue
&lt;/h4&gt;

&lt;p&gt;useDeferredValue will let you defer re-rendering a non-urgent part of the tree. Remember we talked about non-urgent rendering?   &lt;strong&gt;It is no fixed time delay, so React will attempt the deferred render right after the first render is reflected on the screen.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  c. useSyncExternalStore
&lt;/h4&gt;

&lt;p&gt;useSyncExternalStore is a new hook that allows external stores to support concurrent reads by forcing updates to the store to be synchronous. &lt;strong&gt;It removes the need for useEffect when implementing subscriptions to external data sources.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Code snippet:&lt;/p&gt;

&lt;pre&gt;   const state = useSyncExternalStore(subscribe, getSnapshot[, getServerSnapshot]);
&lt;/pre&gt; 

&lt;p&gt;&lt;code&gt;subscribe&lt;/code&gt;: function to register a callback that is called whenever the store changes.&lt;br&gt;
&lt;code&gt;getSnapshot&lt;/code&gt;: function that returns the current value of the store.&lt;br&gt;
&lt;code&gt;getServerSnapshot&lt;/code&gt;: function that returns the snapshot used during server rendering.&lt;/p&gt;

&lt;h4&gt;
  
  
  d. useInsertionEffect
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;useInsertionEffect(didUpdate);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;useInsertionEffect is a new hook that allows CSS-in-JS libraries to address performance issues of injecting styles in render. &lt;strong&gt;This hook will run after the DOM is mutated, but before layout effects read the new layout.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This hook will help in calculating layout in sync with the concurrent re-rendering.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are others small but significant updates too - for example using the &lt;strong&gt;&lt;code&gt;createRoot()&lt;/code&gt;&lt;/strong&gt; hook rather than &lt;strong&gt;&lt;code&gt;ReactDOM.render&lt;/code&gt;&lt;/strong&gt;. This method will be used to render a DOM element and umount using &lt;strong&gt;&lt;code&gt;root.unmount()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Other than than React also have streaming Suspense support for servers using &lt;strong&gt;&lt;code&gt;renderToPipeableStream&lt;/code&gt;&lt;/strong&gt;&amp;amp; &lt;strong&gt;&lt;code&gt;renderToReadableStream&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;React developers keeps on focusing on the enhancement and improvement and couple of bug fixes in this released version. The update is not meticulous and can be done in a morning session, itself. So what's the wait for , application developers? Let's upgrade our library and start working! Kudos to the React team!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A Developer's Journey</title>
      <dc:creator>Bidisha Das</dc:creator>
      <pubDate>Fri, 01 Apr 2022 11:26:26 +0000</pubDate>
      <link>https://dev.to/officialbidisha/a-developers-journey-1oii</link>
      <guid>https://dev.to/officialbidisha/a-developers-journey-1oii</guid>
      <description>&lt;p&gt;As I sit to write this, I need to recollect my last 4 years. Initially, I never wanted to be a developer, my passion was to become a writer. But here I am today, being a developer, a coder and understanding that every piece of code is a story. &lt;/p&gt;

&lt;p&gt;On my first day of engineering college I was skeptical whether I would be able to cope-up with the syllabus because I was always unsure of my mathematical aptitude. But here is a story of overcoming fears. Initially, I didn't think that I would bring in decent grades, but I did. Not once, at all but eventually.&lt;/p&gt;

&lt;p&gt;My journey of development started only in the beginning of 2019. Till then my knowledge of programming was limited to the curriculum. It was a conflict between my teammates in a project which we were preparing for placement,and a few cuss words that shattered my confidence. Though I couldn't say anything at first, I knew that this needed a reply. So I came out of that project and looking back today that was one of the best and basic step I took in last 3 years for my own growth. This didn't happen in a day. Professor Chatterjee at that time, clearly told me,"Bidisha, either you depend on her, and listen to her bullshit or come out of it and do something on your own." I am thankful that I listened to it. I am thankful to him for this reason and so many others. &lt;/p&gt;

&lt;p&gt;But I didn't know where to start. I guess the timing was appropriate when my professor from CSE department gave me and a batchmate a task to do, a library management project. This batchmate of mine, named Meghanto was always bright and intelligent. It is still a wonder to me why he agreed to work with me, held so much patience for me. But in the whole process, we became friends. There was a point in time, whenever there was a hackathon, nobody wanted to participate with me. However, he was the first person who showed me the willingness. Not just that, there were days, I didn't understand &lt;em&gt;documentation&lt;/em&gt;, I struggled with basic things, how to make an API call, what is a stateful and what is a stateless request. However, he stood by me. He would tell me, "Bidisha, read the &lt;strong&gt;goddamn documentation&lt;/strong&gt;, or I will break your head. His famous dialog of &lt;strong&gt;Tinker with Code&lt;/strong&gt; still helps me think, to this date." The amount of effort he put in me for bringing up my standard of thought process and imagination is something I will forever be grateful for. He introduced me to Vue.js. So I still call him my Evan You. &lt;/p&gt;

&lt;p&gt;Then came my first hackathon. Throughout this whole time, behind every small,little progress we made, DC Sir (who gave us the project) always pushed us to do better. I remember asking him few days before the hackathon, "I won't be able to do it. I don't have that brain. What's the use of humiliating myself?" And he said, "Give it a try, give it. If you're not selected also, you knew you tried. The worse thing that can happen is a rejection."&lt;/p&gt;

&lt;p&gt;Honestly, in HackwithInfy, I sat in the first round knowing I wouldn't be able to crack it. But I wanted to do it for DC Sir. Because I didn't want to let him down. I practiced hard for it with no hope to clear it. &lt;strong&gt;Hackerrank&lt;/strong&gt; and &lt;strong&gt;Hackerearth&lt;/strong&gt; was my place of practice. I wanted to come out of the hall and tell him, "Sir, I tried. But I won't be able to clear it. But I really really tried." I wanted to do it for the person, the only person, who had shown faith in me. &lt;/p&gt;

&lt;p&gt;To my surprise, after solving 1.7/3 questions, I qualified my first round. My close friend Dipan, when he told me that I cleared it, I couldn't believe my ears. In this phase, my friends Reshmina, Dipan, Shreya, they did support me to a great extent, We all need our emotional support and somewhere these are the people I would always know had my back, then. All the more was I prepared to sit in my second round. And I did.&lt;/p&gt;

&lt;p&gt;This time I practiced and practiced. It didn't matter. I felt joyous when I was able to solve something, and didn't want to give up. In the second round, I solved 2.2/3 problems and got an interview call. Eventually, with the Library Management Project I and Meghanto made using &lt;strong&gt;Vue.js&lt;/strong&gt;, &lt;strong&gt;Spring Boot&lt;/strong&gt; - we both cracked the HackwithInfy interview.  &lt;/p&gt;




&lt;p&gt;My second phase started during the lockdown. When I couldn't clear the Associate examination for CTS, it broke my confidence again and this time I knew projects are not enough anymore. In order to close the interview process, I needed to pass algorithms and my problem solving ability needed to be increased. &lt;/p&gt;

&lt;p&gt;I was introduced to &lt;strong&gt;CodeChef&lt;/strong&gt;. Anirban and Meganto - my close pals, had pushed me a lot, and there were days in that &lt;strong&gt;10 days CodeChef Long Challenge&lt;/strong&gt; where I was unable to solve and problem and my stars used to go down. In this phase, these people motivated me. My frontend development skills was sharpened by Debjoy - a guy who hands down has better knowledge and skills than I will ever have.&lt;/p&gt;

&lt;p&gt;Had it not been them, I would have given up long back. There are names that I would love to mention here but am witholding - who celebrated with my success and cheered me up in my downfall.&lt;/p&gt;

&lt;p&gt;Next, I sat for Hackathons on Hackerearth. I got calls from &lt;strong&gt;BNY Mellon, American Express, AutoRABIT&lt;/strong&gt; and finally cleared AutoRABIT. They provided me with a more than average package, a good work culture and most of all a chance. &lt;strong&gt;I would always be thankful to AutoRABIT for hiring me. I am sure they had options but still they chose me, took a chance with me, for this I will always be grateful.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Coming to my work life, I had learnt a lot. When I initially joined, my first training project, was in Spring Boot and OlingoData. My tech lead Naresh Ananthapalli was one of the most calm, cool-headed and clear-minded developers I had seen. As a fresher, me and my teammate, Shaurya - we used to make hell lot of mistake and he always used to be patient and guide us through. At that time, a lot of times I got stuck a particular colleague had helped me in debugging. From this person I have learnt to keep good spirit when you solution does not work and have admired his coding skills. &lt;/p&gt;

&lt;p&gt;When I was put into frontend development, I was happy because I was more inclined to that,but skeptical too. I was initially put into the modernisation team. I learnt a lot here. From my senior developer, staying in US, I have learnt the value of how to handle a team, and giving estimates -I remember giving too low estimate for a small task when he corrected me.Most of all, I have learnt how to make people feel homely and comfortable providing assurance from this person. There was another transformation I went through. I had learnt a lot from him and he had helped me improve my skills with a steep slope. &lt;/p&gt;

&lt;p&gt;From one of my senior developer from Bulgaria,  - I learnt that knowing a framework is not good enough unless you know the basics of it. It was a grilling process but I was able to cope up with it. I rememeber crying the night I was asked to develop Progress Button because I failed and made mistake so many times. I thought I am not good enough but I did. &lt;/p&gt;

&lt;p&gt;I would like to mention my manager here. He has influenced my coding style to a great extent. I am going to put it point blank, my manager has been one of my biggest support in terms of guidance,and contribution in my career. He always motivated me, showed confidence in me when I was unable to trust myself. He put in faith in me when I was unable to focus. He never shouted at me, had been patient and understanding. I do not think I would ever come across a better human being and a manager, than him. &lt;/p&gt;

&lt;p&gt;Out of having the curiosity to understand market standard and getting inspired by a colleague who switched - I started browsing opportunities. Only recently did I get an offer from a named product based startup. But about that, in some other post!&lt;br&gt;
For now, this is it. &lt;/p&gt;

&lt;h2&gt;
  
  
  I still have a lot to learn and I hope all goes well. I will keep hustling and one day I will be there.
&lt;/h2&gt;

</description>
      <category>beginners</category>
      <category>developers</category>
      <category>podcast</category>
    </item>
  </channel>
</rss>
