<?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>Forem: Senior Developer</title>
    <description>The latest articles on Forem by Senior Developer (@starneit).</description>
    <link>https://forem.com/starneit</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F335880%2Fd0f6f93e-436c-4e98-9092-0f477aa21400.png</url>
      <title>Forem: Senior Developer</title>
      <link>https://forem.com/starneit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/starneit"/>
    <language>en</language>
    <item>
      <title>Differentiating Zustand and Redux</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Tue, 09 Jul 2024 18:45:08 +0000</pubDate>
      <link>https://forem.com/starneit/differentiating-zustand-and-redux-426i</link>
      <guid>https://forem.com/starneit/differentiating-zustand-and-redux-426i</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%2F8q5q0n01x21zzrd631nu.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%2F8q5q0n01x21zzrd631nu.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Explore the differences between Zustand and Redux, two popular state management libraries in React. Efficient state management is crucial for complex web applications, and both Zustand and Redux offer unique solutions. In this article, we will explore their capabilities, application scenarios, and performance attributes. Whether you are an experienced React developer or new to state management, grasping these distinctions will enable you to make well-informed choices for your projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definitions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Zustand:
&lt;/h3&gt;

&lt;p&gt;Zustand is a lightweight state management library for React applications. It offers a simple and intuitive API, making it easy to manage and share state across components. Zustand follows a minimalist approach and leverages the React hooks system to provide reactive state updates. With its small bundle size and emphasis on performance, Zustand is ideal for smaller projects or situations where a lightweight state management solution is preferred.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redux:
&lt;/h3&gt;

&lt;p&gt;Redux is a powerful state management library for React and other JavaScript applications. It implements the Flux architecture and utilizes a single immutable state tree, providing a predictable state management system. Redux follows strict principles of data flow, making it suitable for large-scale applications with complex state management needs. While Redux requires some boilerplate code, it offers features like middleware and time-travel debugging, which can be valuable for more extensive projects with complex state interactions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why choose Zustand ?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Simplicity: Zustand adopts a minimalist and straightforward API, making it easier to set up and use compared to Redux. With Zustand, developers can manage state with less boilerplate code and have a more streamlined experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lightweight: Zustand has a smaller bundle size compared to Redux. This smaller footprint is advantageous for applications that prioritize performance and loading speed, especially in scenarios where reducing bundle size is crucial.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React Hooks Integration: Zustand seamlessly integrates with React’s hooks system. It leverages React hooks like useReducer and useContext, providing a more native and familiar development experience for React developers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Less Boilerplate Code: Zustand reduces the need for extensive boilerplate code that is often associated with Redux. This leads to a more concise and efficient codebase, which is easier to maintain and understand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No Immutable State Tree: Unlike Redux, Zustand does not require developers to work with an immutable state tree. This flexibility simplifies state updates and avoids the need for deep cloning of objects, resulting in a more straightforward development process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance: Due to its lightweight nature and streamlined approach, Zustand can offer better performance in certain scenarios compared to Redux. Smaller bundles and reduced overhead contribute to improved application speed and responsiveness.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easy Learning Curve: Zustand’s simplicity and close integration with React make it more accessible for developers, particularly those who are new to state management or prefer a more straightforward approach.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why choose Redux
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Established Ecosystem: Redux has a mature and well-established ecosystem with a vast community, extensive documentation, and many third-party libraries, making it a reliable choice for complex projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Predictable State Management: Redux strictly follows data flow principles, ensuring a predictable and consistent approach to managing state, making it easier to debug.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Time-Travel Debugging: Redux’s time-travel debugging allows developers to inspect and replay actions, aiding in understanding state changes over time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Middleware Support: Redux offers robust middleware support, allowing easy integration of features like logging and asynchronous operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Centralized State: Redux promotes centralized state management, simplifying data synchronization across components in large applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thorough Documentation: Redux has extensive documentation and a large community, providing ample learning resources and support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broad Adoption: Being widely used, Redux enjoys a large and active community with plenty of resources and community support.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;In conclusion, Zustand and Redux offer distinct advantages for state management. Zustand’s simplicity and lightweight nature make it ideal for smaller projects, while Redux’s mature ecosystem and predictable state management excel in larger, complex applications. The choice between the two depends on project size, complexity, and development preferences. Both libraries empower developers to create efficient and robust React applications tailored to their specific needs.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>State Management with RxJS and React</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Tue, 09 Jul 2024 18:42:13 +0000</pubDate>
      <link>https://forem.com/starneit/state-management-with-rxjs-and-react-32km</link>
      <guid>https://forem.com/starneit/state-management-with-rxjs-and-react-32km</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%2Fm4us2az1jymf1yr3l7ey.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%2Fm4us2az1jymf1yr3l7ey.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Building big web apps can be tricky, especially when you have lots of different pieces of information to keep track of. But don’t worry, RxJS is here to help! It’s like a really cool tool that helps you manage all your data in one place.&lt;/p&gt;

&lt;p&gt;With RxJS, you can create these things called “streams of data” that different parts of your app can use. It’s like a big river flowing through your app, keeping everything connected and in sync.&lt;/p&gt;

&lt;p&gt;In this article, we’ll show you how to use RxJS to build web apps that are really easy to manage and work great. By the end of the article, you’ll know how to use RxJS to manage all your data and build even bigger and better web apps!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why RxJS for State Management ?
&lt;/h2&gt;

&lt;p&gt;Hey, do you ever get confused when you’re building a big web app and you have lots of different pieces of information to keep track of? That’s where RxJS comes in! It’s like a really cool library that helps you manage all your data in one place.&lt;/p&gt;

&lt;p&gt;With RxJS, you can create streams of data that different parts of your app can use. It’s kind of like a river flowing through your app, keeping everything connected and in sync.&lt;/p&gt;

&lt;p&gt;RxJS also helps you break down your app into smaller pieces, which is like having different rooms in your house for different stuff. That way, it’s easier to keep everything organized and find what you need.&lt;/p&gt;

&lt;p&gt;Overall, RxJS is a great tool for managing data in big web apps. Whether you’re building a simple app or a really big one, RxJS can help you keep everything under control!&lt;/p&gt;

&lt;h2&gt;
  
  
  A to-do list example
&lt;/h2&gt;

&lt;p&gt;The easiest way to apply a new technology or a new proof of concept is to make a to-do list.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Store:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const subject = new Subject();

const initialState: Task[] = [];

let state = initialState;

export const todoStore = {
  init: () =&amp;gt; {
    subject.next(state);
  },
  subscribe: (setState: any) =&amp;gt; {
    subject.subscribe(setState);
  },
  addTask: (content: string) =&amp;gt; {
    const task = {
      content,
      id: uid(),
      isDone: false,
    };
    state = [...state, task];
    subject.next(state);
  },
  removeTask: (id: string) =&amp;gt; {
    const tasks = state.filter((task) =&amp;gt; task.id !== id);
    state = tasks;
    subject.next(state);
  },
  completeTask: (id: string) =&amp;gt; {
    const tasks = state.map((task) =&amp;gt; {
      if (task.id === id) {
        task.isDone = !task.isDone;
      }
      return task;
    });
    state = tasks;
    subject.next(state);
  },
  initialState,
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code defines a simple store for managing a to-do list using RxJS. The store is implemented using a &lt;code&gt;Subject&lt;/code&gt; and provides methods for adding, removing, and completing tasks.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;init&lt;/code&gt; function initializes the store by publishing the current state to the subject using &lt;code&gt;subject.next(state)&lt;/code&gt;. This function is typically called when the app is first loaded to ensure that the store is up to date.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;subscribe&lt;/code&gt; function allows components to subscribe to changes in the store. When the store is updated, the &lt;code&gt;setState&lt;/code&gt; function passed to &lt;code&gt;subscribe&lt;/code&gt; will be called with the updated state. This function is typically used by components that need to display the current state of the store.&lt;/p&gt;

&lt;p&gt;Overall, &lt;code&gt;init&lt;/code&gt; and &lt;code&gt;subscribe&lt;/code&gt; are two important functions in this code that enable developers to manage the state of a to-do list using RxJS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage:
&lt;/h3&gt;

&lt;p&gt;It’s very easy to implement this kind of state management, just do this one the highest level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [tasks, setTasks] = useState&amp;lt;Task[]&amp;gt;([]);

  useEffect(() =&amp;gt; {
    todoStore.subscribe(setTasks);
    todoStore.init();
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code uses React hooks to subscribe to and initialize a store that manages a to-do list using RxJS.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;useState&lt;/code&gt; hook creates a state variable named &lt;code&gt;tasks&lt;/code&gt; and a function named &lt;code&gt;setTasks&lt;/code&gt; for updating that state. The &lt;code&gt;[]&lt;/code&gt; argument passed to &lt;code&gt;useState&lt;/code&gt; sets the initial value of &lt;code&gt;tasks&lt;/code&gt; to an empty array.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; hook is used to subscribe to and initialize the &lt;code&gt;todoStore&lt;/code&gt;. The &lt;code&gt;todoStore.subscribe(setTasks)&lt;/code&gt; line subscribes the &lt;code&gt;setTasks&lt;/code&gt; function to changes in the store. This means that whenever the store is updated, &lt;code&gt;setTasks&lt;/code&gt; will be called with the updated state, and &lt;code&gt;tasks&lt;/code&gt; will be updated accordingly.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;todoStore.init()&lt;/code&gt; function initializes the store by publishing the current state to the subject using &lt;code&gt;subject.next(state)&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;So that’s it! We’ve learned how to use RxJS and React to build a to-do list application. We used RxJS to manage the state of the application and React to display the current state to the user.&lt;/p&gt;

&lt;p&gt;We saw how RxJS provides a powerful set of tools for managing state, including observables, operators, and subjects. And we also learned how to use React hooks like useState and useEffect to update the application state in real-time.&lt;/p&gt;

&lt;p&gt;By using RxJS and React together, we’ve built a cool app that’s easy to use and maintain. And we’ve learned some really valuable skills that we can use to build even more amazing web applications in the future!&lt;/p&gt;

&lt;p&gt;If you think the article is too obscure, check these out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source Code: &lt;a href="https://github.com/starneit/rxjs-state-poc" rel="noopener noreferrer"&gt;https://github.com/starneit/rxjs-state-poc&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Demo: &lt;a href="https://rxjs-poc.web.app/" rel="noopener noreferrer"&gt;https://rxjs-poc.web.app/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Underrated React Hook - useSyncExternalStore</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Tue, 09 Jul 2024 18:37:26 +0000</pubDate>
      <link>https://forem.com/starneit/underrated-react-hook-usesyncexternalstore-4igj</link>
      <guid>https://forem.com/starneit/underrated-react-hook-usesyncexternalstore-4igj</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%2Fgg6y2u0n66mdrk16b6d9.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%2Fgg6y2u0n66mdrk16b6d9.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Discover a hidden powerhouse in the React ecosystem: the “useSyncExternalStore” hook. This article delves into its transformative potential, challenging traditional state management paradigms. By seamlessly integrating external data sources and enhancing cross-component communication, this hook offers an unconventional yet powerful approach.&lt;/p&gt;

&lt;p&gt;Journey with us as we demystify &lt;strong&gt;useSyncExternalStore&lt;/strong&gt;. We’ll dissect its mechanics, unveil its benefits, and showcase practical applications through real-world examples. By the end, you’ll grasp how to wield this hook to streamline complexity, boost performance, and bring a new level of organization to your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;According to React, &lt;code&gt;useSyncExternalStore&lt;/code&gt; is a React Hook that lets you subscribe to an external store. But what is an “external store” exactly ? It literally takes 2 functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;subscribe&lt;/code&gt; function should subscribe to the store and return a function that unsubscribes.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;getSnapshot&lt;/code&gt; function should read a snapshot of the data from the store.
Okay it’s might be hard to get at first. We can go into the example.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Demo
&lt;/h2&gt;

&lt;p&gt;For our demo today, I will go into a classic application: The “Todo List”.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Store
&lt;/h3&gt;

&lt;p&gt;First, we have to define the initial state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export type Task = {
  id: string;
  content: string;
  isDone: boolean;
};

export type InitialState = {
  todos: Task[];
};

export const initialState: InitialState = { todos: [] };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that I defined the types and then created the state that has todos as an empty array&lt;/p&gt;

&lt;p&gt;Now is the reducer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function reducer(state: InitialState, action: any) {
  switch (action.type) {
    case "ADD_TASK":
      const task = {
        content: action.payload,
        id: uid(),
        isDone: false,
      };
      return {
        ...state,
        todos: [...state.todos, task],
      };

    case "REMOVE_TASK":
      return {
        ...state,
        todos: state.todos.filter((task) =&amp;gt; task.id !== action.payload),
      };

    case "COMPLETE_TASK":
      const tasks = state.todos.map((task) =&amp;gt; {
        if (task.id === action.payload) {
          task.isDone = !task.isDone;
        }
        return task;
      });
      return {
        ...state,
        todos: tasks,
      };

    default:
      return state;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our reducer only has 3 actions: &lt;code&gt;ADD_TASK&lt;/code&gt;, &lt;code&gt;REMOVE_TASK&lt;/code&gt; and &lt;code&gt;COMPLETE_TASK&lt;/code&gt;. This is the classic example of a to-do list logic.&lt;/p&gt;

&lt;p&gt;Finally, what we are waiting for, the store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let listeners: any[] = [];

function createStore(reducer: any, initialState: InitialState) {
  let state = initialState;

  function getState() {
    return state;
  }

  function dispatch(action: any) {
    state = reducer(state, action);

    emitChange();
  }

  function subscribe(listener: any) {
    listeners = [...listeners, listener];
    return () =&amp;gt; {
      listeners = listeners.filter((l) =&amp;gt; l !== listener);
    };
  }

  const store = {
    dispatch,
    getState,
    subscribe,
  };

  return store;
}

function emitChange() {
  for (let listener of listeners) {
    listener();
  }
}

export const store = createStore(reducer, initialState);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code snippet illustrates the creation of a simple Redux-like state management system in TypeScript. Here’s a breakdown of how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;listeners&lt;/code&gt; Array: This array holds a list of listener functions that will be notified whenever the state changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;createStore&lt;/code&gt; Function: This function is responsible for creating a Redux-style store. It takes two parameters:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;reducer&lt;/code&gt;: A reducer function responsible for calculating the next state based on the current state and dispatched action.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;initialState&lt;/code&gt;: The initial state of the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;state&lt;/code&gt;: This variable holds the current state of the application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;getState&lt;/code&gt; Function: Returns the current state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;dispatch&lt;/code&gt; Function: Accepts an action object, passes it to the reducer along with the current state, updates the state with the result, and then calls the emitChange function to notify listeners about the state change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;subscribe&lt;/code&gt; Function: Accepts a listener function, adds it to the listeners array, and returns a cleanup function that can be called to remove the listener.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;store&lt;/code&gt; Object: The created store object holds references to the dispatch, getState, and subscribe functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;emitChange&lt;/code&gt; Function: Iterates through the listeners array and invokes each listener function, notifying them of a state change.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the end of the code, a &lt;code&gt;store&lt;/code&gt; is created using the &lt;code&gt;createStore&lt;/code&gt; function, with a given reducer and initial state. This store can now be imported and used in other parts of the application to manage and control the state.&lt;/p&gt;

&lt;p&gt;It’s important to note that this code provides a simplified implementation of a state management system and lacks some advanced features and optimizations found in libraries like Redux. However, it serves as a great starting point to understand the basic concepts of state management using listeners and a reducer function.&lt;/p&gt;

&lt;p&gt;To use the &lt;code&gt;useSyncExternalStore&lt;/code&gt; hook. We can get the state 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;const { todos } = useSyncExternalStore(store.subscribe, store.getState);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this hook call, we can access the store globally and dynamically, while maintain the readability and maintainability&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros and Cons
&lt;/h2&gt;

&lt;p&gt;The “useSyncExternalStore” hook presents both advantages and potential drawbacks in the context of state management within a React application:&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seamless Integration with External Sources&lt;/strong&gt;: The hook enables effortless integration with external data sources, promoting a unified approach to state management. This integration can simplify the handling of data from various origins, enhancing the application’s cohesion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross-Component Communication&lt;/strong&gt;: “useSyncExternalStore” facilitates efficient communication between components, streamlining the sharing of data and reducing the need for complex prop drilling or context management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Improvements&lt;/strong&gt;: By centralizing state management and minimizing the propagation of state updates, this hook has the potential to optimize rendering performance, resulting in a more responsive and efficient application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplicity and Clean Code&lt;/strong&gt;: The hook’s abstracted API can lead to cleaner and more organized code, making it easier to understand and maintain, particularly in large-scale applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduced Boilerplate&lt;/strong&gt;: “useSyncExternalStore” may reduce the need for writing redundant code for state management, providing a concise and consistent way to manage application-wide state.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;: Developers unfamiliar with this hook might experience a learning curve when transitioning from more established state management solutions. Adapting to a new approach could initially slow down development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customization Limitations&lt;/strong&gt;: The hook’s predefined functionalities might not align perfectly with every application’s unique requirements. Customizing behavior beyond the hook’s capabilities might necessitate additional workarounds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Potential Abstraction Overhead&lt;/strong&gt;: Depending on its internal mechanics, the hook might introduce a slight overhead in performance or memory usage compared to more optimized solutions tailored specifically for the application’s needs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community and Ecosystem&lt;/strong&gt;: As an underrated or lesser-known hook, “useSyncExternalStore” might lack a well-established community and comprehensive ecosystem, potentially resulting in fewer available resources or third-party libraries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatibility and Future Updates&lt;/strong&gt;: Compatibility with future versions of React and potential updates to the hook itself could be points of concern. Ensuring long-term support and seamless upgrades may require extra diligence.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;In summary, &lt;code&gt;useSyncExternalStore&lt;/code&gt; offers a unique approach to state management, emphasizing seamless integration and cross-component communication. While it provides several benefits, such as improved performance and simplified code, developers should carefully evaluate its compatibility with their project’s requirements and consider the potential learning curve and limitations.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Generating Optimized Image Formats with Node.js</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Thu, 04 Jul 2024 18:02:39 +0000</pubDate>
      <link>https://forem.com/starneit/generating-optimized-image-formats-with-nodejs-4955</link>
      <guid>https://forem.com/starneit/generating-optimized-image-formats-with-nodejs-4955</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%2Ffqncm6zxqg3qeajc9agv.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%2Ffqncm6zxqg3qeajc9agv.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Images are an important part of any web application, but they can also be a major source of performance issues if not optimized properly. In this article, we’ll cover how to use Node.js and React to automatically generate optimized image formats and display them in the best format for the user’s browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up
&lt;/h2&gt;

&lt;p&gt;First we need a library that handle image processing for us, and &lt;strong&gt;sharp&lt;/strong&gt; is what I chose&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;npm i sharp&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sharp is a high-performance Node.js library for image processing and manipulation. It is designed to be fast and memory-efficient, making it ideal for processing large images and generating multiple image formats.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generation Script
&lt;/h2&gt;

&lt;p&gt;The first step in optimizing images for the web is to generate multiple formats of each image, each with its own advantages and disadvantages. Some formats, such as JPEG, are good for complex images with many colors, while others, such as WebP, are better for simpler images with fewer colors.&lt;/p&gt;

&lt;p&gt;To generate different image formats, we can use Node.js and the Sharp image processing library. Here’s an example script that generates avif and webp formats for each image in the images folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sharp = require("sharp");
const fs = require("fs");

const inputFolder = "images";
const outputFolder = "output";

const formats = ["avif", "webp"];

if (!fs.existsSync(outputFolder)) {
  fs.mkdirSync(outputFolder);
}

fs.readdir(inputFolder, (err, files) =&amp;gt; {
  if (err) {
    console.error(err);
    return;
  }

  files.forEach((file) =&amp;gt; {
    if (
      file.endsWith(".jpg") ||
      file.endsWith(".jpeg") ||
      file.endsWith(".png")
    ) {
      const inputPath = `${inputFolder}/${file}`;
      const name = file.substring(0, file.lastIndexOf("."));

      formats.forEach((format) =&amp;gt; {
        const outputPath = `${outputFolder}/${name}.${format}`;

        if (!fs.existsSync(outputPath)) {
          sharp(inputPath)
            .toFormat(format, { quality: 80 })
            .toFile(outputPath, (err) =&amp;gt; {
              if (err) {
                console.error(err);
              } else {
                console.log(`${name}.${format} saved`);
              }
            });
        }
      });
    }
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sharp = require("sharp");
const fs = require("fs");

const inputFolder = "images";
const outputFolder = "output";

const formats = ["avif", "webp"];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In these lines, the script imports the &lt;strong&gt;sharp&lt;/strong&gt; and &lt;strong&gt;fs&lt;/strong&gt; libraries, sets the input folder to &lt;strong&gt;images&lt;/strong&gt;, the output folder to &lt;strong&gt;output&lt;/strong&gt;, and defines the formats to be generated as &lt;strong&gt;avif&lt;/strong&gt; and &lt;strong&gt;webp&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!fs.existsSync(outputFolder)) {
  fs.mkdirSync(outputFolder);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the script checks if the &lt;strong&gt;outputFolder&lt;/strong&gt; exists, and if it doesn’t, creates it using &lt;code&gt;fs.mkdirSync()&lt;/code&gt;. This ensures that the output folder exists before generating any images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fs.readdir(inputFolder, (err, files) =&amp;gt; {
  if (err) {
    console.error(err);
    return;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code reads the contents of the inputFolder using &lt;code&gt;fs.readdir()&lt;/code&gt;. If there is an error, it logs the error to the console and returns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;files.forEach(file =&amp;gt; {
    if (file.endsWith('.jpg') || file.endsWith('.jpeg') || file.endsWith('.png')) {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code loops through each file in the inputFolder using &lt;code&gt;files.forEach()&lt;/code&gt;. If the file name ends with .jpg, .jpeg, or .png, it proceeds to generate the corresponding avif and webp files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const inputPath = `${inputFolder}/${file}`;
const name = file.substring(0, file.lastIndexOf("."));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the script defines the input file path as inputPath, and extracts the file name without the extension to be used as the output file name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;formats.forEach((format) =&amp;gt; {
  const outputPath = `${outputFolder}/${name}.${format}`;

  if (!fs.existsSync(outputPath)) {
    sharp(inputPath)
      .toFormat(format, { quality: 80 })
      .toFile(outputPath, (err) =&amp;gt; {
        if (err) {
          console.error(err);
        } else {
          console.log(`${name}.${format} saved`);
        }
      });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the script loops through each format (i.e. avif and webp) using &lt;code&gt;formats.forEach()&lt;/code&gt;. For each format, it defines the output file path as outputPath.&lt;/p&gt;

&lt;p&gt;If the output file does not already exist, it uses Sharp’s &lt;code&gt;toFormat()&lt;/code&gt; function to generate the corresponding image in the specified format with a quality of 80. It then saves the output file using &lt;code&gt;toFile()&lt;/code&gt;, and logs a message to the console indicating that the file has been saved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Display Optimized Images in React
&lt;/h2&gt;

&lt;p&gt;Once we have generated multiple optimized image formats for each input image, we can display them in our React application. To do this, we can use the HTML &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt; elements to specify the different image sources for different formats. Here’s an example React component that takes an image name as a prop and displays the image in the best format for the user’s browser:&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 from "react";

const Image = ({ name }) =&amp;gt; {
  const avifSrc = `/images/${name}.avif`;
  const webpSrc = `/images/${name}.webp`;
  const jpgSrc = `/images/${name}.jpg`;

  return (
    &amp;lt;picture&amp;gt;
      &amp;lt;source srcSet={avifSrc} type="image/avif" /&amp;gt;
      &amp;lt;source srcSet={webpSrc} type="image/webp" /&amp;gt;
      &amp;lt;img src={jpgSrc} alt={name} /&amp;gt;
    &amp;lt;/picture&amp;gt;
  );
};

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

&lt;/div&gt;



&lt;p&gt;This code defines three different image source URLs based on the name prop passed in:&lt;/p&gt;

&lt;p&gt;avifSrc corresponds to the avif format of the image.&lt;br&gt;
webpSrc corresponds to the webp format of the image.&lt;br&gt;
jpgSrc corresponds to the standard jpg format of the image, which will be used as a fallback for browsers that do not support avif or webp.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  return (
    &amp;lt;picture&amp;gt;
      &amp;lt;source srcSet={avifSrc} type="image/avif" /&amp;gt;
      &amp;lt;source srcSet={webpSrc} type="image/webp" /&amp;gt;
      &amp;lt;img src={jpgSrc} alt={name} /&amp;gt;
    &amp;lt;/picture&amp;gt;
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the script returns a &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element that displays the image in the best format for the user’s browser, based on the available formats. Inside the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element, there are two &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt; elements, one for avif and one for webp. These elements specify the different image sources for different formats using the srcSet attribute and the type attribute to indicate the MIME type of each format.&lt;/p&gt;

&lt;p&gt;Finally, there is a fallback &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element that displays the image in the standard jpg format for browsers that do not support avif or webp. This element uses the src attribute to specify the image source and the alt attribute to provide alternate text for the image.&lt;/p&gt;

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

&lt;p&gt;Images on websites can be slow to load and don’t always look good on different devices. It’s important to make them load faster and look better so people can enjoy your website more. We learned how to use special tools like Sharp and HTML’s &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt; to make different versions of the same image and show the best one for each device. By doing this, our website will be faster and look better for everyone who uses it!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>node</category>
    </item>
    <item>
      <title>Differentiating onclick and addEventListener in JavaScript</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Thu, 04 Jul 2024 17:15:06 +0000</pubDate>
      <link>https://forem.com/starneit/differentiating-onclick-and-addeventlistener-in-javascript-bh3</link>
      <guid>https://forem.com/starneit/differentiating-onclick-and-addeventlistener-in-javascript-bh3</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%2Fqav3z2wp45k0njywiw45.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%2Fqav3z2wp45k0njywiw45.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This article provides an insightful examination of the contrasting approaches to event handling in JavaScript: the familiar &lt;strong&gt;onclick&lt;/strong&gt; and the versatile &lt;strong&gt;addEventListener&lt;/strong&gt; method. By delving into the nuances of these two mechanisms, we uncover the unique advantages they offer and the scenarios in which they excel. Through comprehensive examples and practical use cases, we’ll dissect the syntax, behavior, and compatibility of both onclick and &lt;strong&gt;addEventListener&lt;/strong&gt;, empowering developers to make informed choices when implementing event-driven interactions in their web applications. Whether it’s a straightforward click action or a more complex event management requirement, this article equips readers with the knowledge to navigate between these two event handling paradigms effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definitions
&lt;/h2&gt;

&lt;p&gt;Here are the definitions:&lt;/p&gt;

&lt;h3&gt;
  
  
  onclick in HTML:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;onclick&lt;/strong&gt; is an HTML attribute used to attach JavaScript code that will execute when a specific element, such as a button or a link, is clicked by the user. This attribute allows developers to define inline event handling directly within the HTML markup. When the element is clicked, the specified JavaScript code is triggered, enabling interactivity and user-initiated actions. While simple to use, onclick is limited to a single event handler and can become cumbersome when managing multiple events on the same element or handling more complex scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  addEventListener in JavaScript:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;addEventListener&lt;/strong&gt; is a method in JavaScript that allows developers to dynamically attach event handlers to HTML elements. It provides a more flexible and robust approach compared to inline event attributes like onclick. With &lt;strong&gt;addEventListener&lt;/strong&gt;, multiple event listeners can be added to the same element, and event handling can be more organized and maintainable. It offers control over event propagation, capturing, and bubbling phases. Additionally, &lt;strong&gt;addEventListener&lt;/strong&gt; accommodates various event types beyond just clicks, expanding its utility for handling a wide range of user interactions and application behaviors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  onclick
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;onclick Example&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;button id="myButton"&amp;gt;Click me&amp;lt;/button&amp;gt;

&amp;lt;script&amp;gt;
  function handleClick() {
    alert("Button clicked!");
  }

  document.getElementById("myButton").onclick = handleClick;
&amp;lt;/script&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the onclick attribute is used to directly assign a JavaScript function (handleClick) to the button’s click event. When the button is clicked, the handleClick function is executed, displaying an alert.&lt;/p&gt;

&lt;h3&gt;
  
  
  addEventListener
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;addEventListener Example&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;button id="myButton"&amp;gt;Click me&amp;lt;/button&amp;gt;

&amp;lt;script&amp;gt;
  function handleClick() {
    alert("Button clicked!");
  }

  document.getElementById("myButton").addEventListener("click", handleClick);
&amp;lt;/script&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;strong&gt;addEventListener&lt;/strong&gt; method is used to attach the same &lt;strong&gt;handleClick&lt;/strong&gt; function to the button’s click event. This method provides more flexibility and allows for multiple event listeners to be added to the same element.&lt;/p&gt;

&lt;h2&gt;
  
  
  Differences
&lt;/h2&gt;

&lt;p&gt;Difference between addEventListener and onclick:&lt;/p&gt;

&lt;h3&gt;
  
  
  addEventListener:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;addEventListener&lt;/strong&gt; allows the addition of multiple events to a specific element.&lt;/li&gt;
&lt;li&gt;It can accept a third argument that provides control over event propagation.&lt;/li&gt;
&lt;li&gt;Events added using &lt;strong&gt;addEventListener&lt;/strong&gt; can only be attached within &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; elements or in external JavaScript files.&lt;/li&gt;
&lt;li&gt;Compatibility may be limited, as it does not work in older versions of Internet Explorer, which use &lt;strong&gt;attachEvent&lt;/strong&gt; instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  onclick:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;onclick&lt;/strong&gt; is used to attach a single event to an element.&lt;/li&gt;
&lt;li&gt;It is essentially a property and may get overwritten.&lt;/li&gt;
&lt;li&gt;Event propagation cannot be controlled directly with &lt;strong&gt;onclick&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onclick&lt;/strong&gt; can also be added directly as an HTML attribute, offering a simpler integration method.&lt;/li&gt;
&lt;li&gt;It is widely supported and functions across various browsers.&lt;/li&gt;
&lt;li&gt;The choice between addEventListener and onclick depends on the complexity of event management required and the compatibility needs of the application.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In conclusion, understanding the distinctions between &lt;strong&gt;addEventListener&lt;/strong&gt; and &lt;strong&gt;onclick&lt;/strong&gt; is essential for effective event handling in JavaScript. While both methods enable interaction and responsiveness, they cater to different levels of complexity and compatibility requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;addEventListener&lt;/strong&gt; emerges as a versatile tool, offering the flexibility to attach multiple events to a single element. Its capacity to control event propagation and its suitability for structured scripting make it a robust choice for modern applications. However, developers should be cautious of its limited compatibility with older browsers.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;onclick&lt;/strong&gt; provides a straightforward means of attaching a single event to an element, making it a suitable choice for simpler interactions. Its direct integration as an HTML attribute streamlines implementation but may lack the comprehensive control and scalability offered by &lt;strong&gt;addEventListener&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the end, the selection between these methods hinges on the project’s scope, desired functionality, and the targeted user base. By grasping the strengths and limitations of each approach, developers can make informed decisions, crafting seamless and responsive web experiences tailored to their unique needs.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Utilizing VisX for React Data Visualization</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Wed, 03 Jul 2024 11:02:26 +0000</pubDate>
      <link>https://forem.com/starneit/utilizing-visx-for-react-data-visualization-f4f</link>
      <guid>https://forem.com/starneit/utilizing-visx-for-react-data-visualization-f4f</guid>
      <description>&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;Welcome to our comprehensive guide on data visualization in React using VisX! Data visualization plays a crucial role in making complex information more understandable and actionable. In this article, we will explore how VisX, a powerful data visualization library built on top of D3, empowers React developers to create stunning and interactive visualizations with ease. Whether you are a seasoned React developer looking to enhance your data presentation skills or a beginner eager to dive into the world of data visualization, this article is your gateway to mastering VisX and unleashing the full potential of data-driven web applications. Join us as we embark on an exciting journey of transforming raw data into beautiful, informative, and impactful visuals with VisX in React. Let's dive in!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Demo
&lt;/h3&gt;

&lt;p&gt;Charts are among the fundamental examples in data visualization. In this article, we will delve into creating a functional Line Chart demo using VisX&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up
&lt;/h3&gt;

&lt;p&gt;VisX is all you going to need in this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @visx/visx 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Typings
&lt;/h3&gt;

&lt;p&gt;First, we need to define some types so It will be safer when coding our app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type CityName = 'New York' | 'San Francisco' | 'Austin';

type TooltipData = {
  bar: SeriesPoint&amp;lt;CityTemperature&amp;gt;;
  key: CityName;
  index: number;
  height: number;
  width: number;
  x: number;
  y: number;
  color: string;
};

type BarStackHorizontalProps = {
  width: number;
  height: number;
  margin?: { top: number; right: number; bottom: number; left: number };
  events?: boolean;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code defines three TypeScript types: CityName, TooltipData, and BarStackHorizontalProps. CityName is a union of three string literals, representing city names. TooltipData holds data for displaying tooltips in a chart. BarStackHorizontalProps defines properties for configuring a horizontal bar stack chart.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mock Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import cityTemperature, { CityTemperature } from '@visx/mock-data/lib/mocks/cityTemperature';

const data = cityTemperature.slice(0, 20);
const keys = Object.keys(data[0]).filter((d) =&amp;gt; d !== 'date') as CityName[];

const temperatureTotals = data.reduce((allTotals, currentDate) =&amp;gt; {
  const totalTemperature = keys.reduce((dailyTotal, k) =&amp;gt; {
    dailyTotal += Number(currentDate[k]);
    return dailyTotal;
  }, 0);
  allTotals.push(totalTemperature);
  return allTotals;
}, [] as number[]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The library itself provides us with plenty of mock data built in. This TypeScript code utilizes the VisX library to work with mock temperature data for cities. It creates a subset of the data, filters and extracts relevant keys, and calculates total temperature values for each entry. The results are stored in the temperatureTotals array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utilities
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const parseDate = timeParse('%Y-%m-%d');
const format = timeFormat('%b %d');
const formatDate = (date: string) =&amp;gt; format(parseDate(date) as Date);

const getDate = (d: CityTemperature) =&amp;gt; d.date;

const temperatureScale = scaleLinear&amp;lt;number&amp;gt;({
  domain: [0, Math.max(...temperatureTotals)],
  nice: true,
});
const dateScale = scaleBand&amp;lt;string&amp;gt;({
  domain: data.map(getDate),
  padding: 0.2,
});
const colorScale = scaleOrdinal&amp;lt;CityName, string&amp;gt;({
  domain: keys,
  range: [red1, red2, red3],
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code defines and initializes several scales for data visualization:&lt;/p&gt;

&lt;p&gt;parseDate and formatDate:&lt;/p&gt;

&lt;p&gt;parseDate is a function that parses date strings in the format %Y-%m-%d and converts them to JavaScript Date objects.&lt;br&gt;
formatDate is a function that takes a date string as input, parses it using parseDate, and then formats it to a new string in the format %b %d. This new formatted string represents the date in abbreviated month and day format.&lt;br&gt;
getDate:&lt;/p&gt;

&lt;p&gt;getDate is a function that takes an object of type CityTemperature (presumably containing temperature data for a city) as input and returns the date property value from that object. It is used to extract the date values from the data array.&lt;br&gt;
temperatureScale, dateScale, and colorScale:&lt;/p&gt;

&lt;p&gt;temperatureScale is a linear scale that is defined using scaleLinear. It sets the domain from 0 to the maximum value of temperatureTotals, and nice: true ensures the scale generates nice, human-readable tick values.&lt;br&gt;
dateScale is a band scale that is defined using scaleBand. It sets the domain to an array of dates extracted from the data array using the getDate function. It also specifies a padding of 0.2 between the bands.&lt;br&gt;
colorScale is an ordinal scale that is defined using scaleOrdinal. It sets the domain to the keys array, which presumably contains city names. The range is an array of color values (e.g., red1, red2, red3), which will be mapped to each unique city name in the keys array.&lt;br&gt;
These scales are commonly used in data visualization to map data values to visual properties such as positions, sizes, and colors. The scales play a crucial role in creating meaningful and visually appealing data visualizations.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tooltip
&lt;/h3&gt;

&lt;p&gt;I have to go to the tooltip first or else the article would be pretty hard to follow. We have to wrap our component with withTooltip from VisX 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;withTooltip&amp;lt;BarStackHorizontalProps, TooltipData&amp;gt;(
  ({
    width,
    height,
    events = false,
    margin = defaultMargin,
    tooltipOpen,
    tooltipLeft,
    tooltipTop,
    tooltipData,
    hideTooltip,
    showTooltip,
  }: BarStackHorizontalProps &amp;amp; WithTooltipProvidedProps&amp;lt;TooltipData&amp;gt;)
Then we can show the tooltip:
{tooltipOpen &amp;amp;&amp;amp; tooltipData &amp;amp;&amp;amp; (
          &amp;lt;Tooltip top={tooltipTop} left={tooltipLeft} style={tooltipStyles}&amp;gt;
            &amp;lt;div style={{ color: colorScale(tooltipData.key) }}&amp;gt;
              &amp;lt;strong&amp;gt;{tooltipData.key}&amp;lt;/strong&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div&amp;gt;{tooltipData.bar.data[tooltipData.key]}℉&amp;lt;/div&amp;gt;
            &amp;lt;div&amp;gt;
              &amp;lt;small&amp;gt;{formatDate(getDate(tooltipData.bar.data))}&amp;lt;/small&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/Tooltip&amp;gt;
        )}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Full code
&lt;/h3&gt;

&lt;p&gt;This is the full implementation of the line chart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg width={width} height={height}&amp;gt;
          &amp;lt;rect width={width} height={height} fill={background} rx={14} /&amp;gt;
          &amp;lt;Group top={margin.top} left={margin.left}&amp;gt;
            &amp;lt;BarStackHorizontal&amp;lt;CityTemperature, CityName&amp;gt;
              data={data}
              keys={keys}
              height={yMax}
              y={getDate}
              xScale={temperatureScale}
              yScale={dateScale}
              color={colorScale}
            &amp;gt;
              {(barStacks) =&amp;gt;
                barStacks.map((barStack) =&amp;gt;
                  barStack.bars.map((bar) =&amp;gt; (
                    &amp;lt;rect
                      key={`barstack-horizontal-${barStack.index}-${bar.index}`}
                      x={bar.x}
                      y={bar.y}
                      width={bar.width}
                      height={bar.height}
                      fill={bar.color}
                      onClick={() =&amp;gt; {
                        if (events) alert(`clicked: ${JSON.stringify(bar)}`);
                      }}
                      onMouseLeave={() =&amp;gt; {
                        tooltipTimeout = window.setTimeout(() =&amp;gt; {
                          hideTooltip();
                        }, 300);
                      }}
                      onMouseMove={() =&amp;gt; {
                        if (tooltipTimeout) clearTimeout(tooltipTimeout);
                        const top = bar.y + margin.top;
                        const left = bar.x + bar.width + margin.left;
                        showTooltip({
                          tooltipData: bar,
                          tooltipTop: top,
                          tooltipLeft: left,
                        });
                      }}
                    /&amp;gt;
                  )),
                )
              }
            &amp;lt;/BarStackHorizontal&amp;gt;
            &amp;lt;AxisLeft
              hideAxisLine
              hideTicks
              scale={dateScale}
              tickFormat={formatDate}
              stroke={red3}
              tickStroke={red3}
              tickLabelProps={{
                fill: red3,
                fontSize: 11,
                textAnchor: 'end',
                dy: '0.33em',
              }}
            /&amp;gt;
            &amp;lt;AxisBottom
              top={yMax}
              scale={temperatureScale}
              stroke={red3}
              tickStroke={red3}
              tickLabelProps={{
                fill: red3,
                fontSize: 11,
                textAnchor: 'middle',
              }}
            /&amp;gt;
          &amp;lt;/Group&amp;gt;
        &amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The result
&lt;/h3&gt;

&lt;p&gt;This would be the result:&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%2Fjxxjx7hvqv0sw10mto6t.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%2Fjxxjx7hvqv0sw10mto6t.png" alt="Image description" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Image description&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In conclusion, VisX shines as a powerful data visualization library for React applications. Its seamless integration with React empowers developers to create visually stunning and interactive data visualizations with ease. By utilizing VisX's extensive array of scales, the process of mapping data to visual elements becomes highly efficient and dynamic. The combination of React and VisX unlocks a world of possibilities for presenting complex data in a clear and engaging manner. Whether you are a seasoned developer or just starting, VisX's strength lies in its ability to transform raw data into compelling visual narratives, making it a valuable asset for any data-driven project. Embrace VisX's capabilities and embark on a journey of crafting captivating and informative data visualizations that leave a lasting impact on your audience.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding TypeScript “as” Keyword</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Wed, 03 Jul 2024 10:53:40 +0000</pubDate>
      <link>https://forem.com/starneit/understanding-typescript-as-keyword-2ne4</link>
      <guid>https://forem.com/starneit/understanding-typescript-as-keyword-2ne4</guid>
      <description>&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;In TypeScript, the "as" keyword is used for type assertion, which allows us to manually set the data type of a variable and prevent the compiler from inferring it on its own. Type assertion is commonly used to treat any type as a specific type, such as a number or string. While type assertion can be useful, it's important to be careful when using it because it can disable type checking and lead to errors if used incorrectly. The "as" keyword is one way to perform type assertion in TypeScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;

&lt;p&gt;In TypeScript, the "as" keyword is utilized for creating type assertions. This allows an object to be considered as a different type than what the compiler originally inferred it to be. To implement the "as" keyword in TypeScript, a specific syntax is used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Variable as TypeOrInterface;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "as" keyword can be used to assert types in TypeScript with the help of a specific syntax. To demonstrate this, let's take a look at an example that utilizes the syntax we previously discussed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let test: unknown = "hello, world";
console.log(test);

let len: number = (test as string).length;
console.log(len);

This will be the output:

hello, world
11 // the length of the string above
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above declares a variable called “test” and assigns it a string value. The length of this string is then calculated by converting “test” from an unknown type to a string type using the "as" keyword. To better understand how this works, try running the code in your own editor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;p&gt;The "as" keyword is a type assertion method in TypeScript and should only be used when we want to assign another data type to a variable and are confident about it. It's important to be careful when using "as" because even a small mistake can result in errors in the code. This keyword is typically used when the type of an object is known, but the compiler is not aware of it. "As" is used to associate the required type with the object or variable for type assertion in TypeScript.&lt;br&gt;
Use the "as" Keyword to Cast Types in TypeScript&lt;br&gt;
In TypeScript, the keyword can be used to convert a type to a slightly more or less specific version of the expected type. To better understand how this works, let's take a look at an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface employee {
    n: string
    id: number
}

function getEmployee(){
    let name : string = “Joe”;
    return {
        n: name, 
        id: 1
    };
}

let firstEmployee  = getEmployee() as employee;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we are using type assertion to link the user object with the "employee" type. This improves the development experience by providing better auto-completion and suggestions. Running the code in your editor will provide a clearer explanation of how this works.&lt;br&gt;
Utilize the "as" keyword for type predicates in TypeScript.&lt;br&gt;
The "as" keyword is also utilized in type predicates, which are type guards that can be used on untyped objects or objects with weak types. To further illustrate this concept, consider the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Employee1 {
    salary(): void;
}

interface Employee2 {
    benefits(): void;
}

function employee1OrEmployee2(): Employee1 | Employee2 {
    let employee1: Employee1 = {
        salary() {
            console.log("salary");
        }
    };
    return employee1;
}

function isEmployee1(person: Employee1 | Employee2): person is Employee1 {
    return (person as Employee1).salary !== undefined;
}

let person = employee1OrEmployee2();
if (isEmployee1(person)) {
    (person as Employee1).salary();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;p&gt;While the "as" keyword can be useful for type assertion in TypeScript, it has some drawbacks that developers should be aware of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It can lead to runtime errors: When using "as" to perform type assertion, the compiler is forced to accept the developer's assertion as true, even if it's not. This can lead to runtime errors if the type assertion is incorrect.&lt;/li&gt;
&lt;li&gt;It can disable type checking: When using "as" to perform type assertion, the compiler's type checking is disabled for that variable or expression. This can make it more difficult to catch type errors and can lead to more bugs in the code.&lt;/li&gt;
&lt;li&gt;It can make the code less readable: Overuse of the "as" keyword can make the code harder to read and understand, especially for developers who are not familiar with the codebase.&lt;/li&gt;
&lt;li&gt;It can be a sign of poor design: In some cases, the need to use "as" for type assertion may indicate a flaw in the design of the code, such as insufficient type information or a poorly defined interface.
To avoid these drawbacks, it's important to use "as" sparingly and only when necessary, and to make sure that the type assertion is accurate and well-supported by the code. It's also important to design interfaces and data structures that provide sufficient type information to the compiler, which can reduce the need for type assertion in the first place.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In conclusion, the "as" keyword can be a useful tool for type assertion in TypeScript, allowing developers to manually specify the type of a variable or expression. However, it's important to use "as" sparingly and only when necessary, as overuse can lead to runtime errors, disable type checking, and make the code less readable. Developers should also be aware that the need for type assertion may indicate a flaw in the design of the code, and should strive to design interfaces and data structures that provide sufficient type information to the compiler. By using "as" judiciously and designing code with type safety in mind, developers can make the most of TypeScript's powerful type system and improve the reliability and maintainability of their code.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Time Travel in React with Immer: A Step-by-Step Tutorial</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Wed, 03 Jul 2024 10:40:02 +0000</pubDate>
      <link>https://forem.com/starneit/time-travel-in-react-with-immer-a-step-by-step-tutorial-78p</link>
      <guid>https://forem.com/starneit/time-travel-in-react-with-immer-a-step-by-step-tutorial-78p</guid>
      <description>&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;In the ever-evolving landscape of front-end development, the ability to manipulate state effectively is a crucial skill. Imagine having the power to rewind and fast-forward through your application's state changes, pinpointing bugs and gaining a deeper understanding of your code's behavior. Welcome to the world of time travel debugging.&lt;br&gt;
In this in-depth tutorial, we will dive into the realm of time travel debugging in React, leveraging the remarkable capabilities of Immer. Immer is a powerful library that simplifies state management by enabling you to work with immutable data structures in a mutable-like manner. But it doesn't stop there – Immer's magic truly shines when combined with time travel debugging, offering developers a profound way to visualize and debug state changes over time.&lt;br&gt;
Throughout this tutorial, we will guide you step-by-step on how to integrate Immer into your React application and unlock the captivating potential of time travel debugging. We will cover essential concepts such as immutability, state transitions, and the magic of Immer's produce function. As we progress, you will witness firsthand how to set up your development environment for time travel debugging, manipulate and navigate state snapshots, and even replay past state sequences.&lt;/p&gt;
&lt;h3&gt;
  
  
  The demo
&lt;/h3&gt;

&lt;p&gt;The upcoming demo will feature a compact app where users can create, resize, and move boxes within an interactive canvas. Notably, the app will incorporate an undo-redo feature, allowing users to easily navigate through their actions. This seamless blend of functionalities offers users the freedom to experiment while ensuring they can effortlessly backtrack or redo their steps. This engaging experience will spotlight the potential of modern front-end development by showcasing a seemingly simple concept turned into a powerful application.&lt;/p&gt;
&lt;h3&gt;
  
  
  Set up
&lt;/h3&gt;

&lt;p&gt;Actually we only need Immer as a compulsory library for this demo, but I also install theme-ui and react-resizable to speed up the development time.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Reducer
&lt;/h3&gt;

&lt;p&gt;First thing we need is a reducer so we can listen to actions and return the desired results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import  { produceWithPatches, applyPatches } from "immer";

export const boxAction = (draft, action) =&amp;gt; {
  const { width, height, id, color, position } = action;
  let box = draft.boxes[draft.selectBox];

  switch (action.type) {
    case "ADD_BOX":
      draft.boxes[id] = {
        id,
        width,
        height,
        color,
        position,
      };
      break;
    case "SELECT_BOX":
      draft.selectBox = id
      break;
    case "MOVE_BOX":
      if (!box) return;
      box.position = position;
      break;
    case "RESIZE_BOX":
      if (!box) return;
      box.width = width;
      box.height = height;
      box.position = position;
      break;
    case "DELETE":
      delete draft.boxes[draft.selectBox];
      break;
    case "APPLY_PATCHES":
      return applyPatches(draft, action.patches);
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can start looking at each action:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ADD_BOX : we add a new box to the store&lt;/li&gt;
&lt;li&gt;SELECT_BOX: we select a box ( to delete, resize or move )&lt;/li&gt;
&lt;li&gt;MOVE_BOX: we move a box to the new position&lt;/li&gt;
&lt;li&gt;RESIZE_BOX: we resize the box&lt;/li&gt;
&lt;li&gt;DELETE: we delete the selected box&lt;/li&gt;
&lt;li&gt;APPLY_PATCHES: we use Immer’s applyPatches function for this. During the run of a producer, Immer can record all the patches that would replay the changes made by the reducer. This function allows us to patch the state
Then we will create a producer using Immer’s produceWithPatches and create a initial state:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const patchGeneratingBoxesReducer = produceWithPatches(boxAction);

export function getInitialState() {
  return {
    boxes: {},
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The dispatch function
&lt;/h3&gt;

&lt;p&gt;Here’s the thing, we need a function that will be called every time we emit an action, and this function should be implemented with a stack, since we will put every “patch” into the stack&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const undoStack = useRef([]);
  const undoStackPointer = useRef(-1);

  const dispatch = useCallback((action, undoable = true) =&amp;gt; {
    setState((currentState) =&amp;gt; {
      const [nextState, patches, inversePatches] = patchGeneratingBoxesReducer(
        currentState,
        action
      );
      if (undoable) {
        const pointer = ++undoStackPointer.current;
        undoStack.current.length = pointer;
        undoStack.current[pointer] = { patches, inversePatches };  
      }
      return nextState;
    });
  }, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t worry, I will explain in details:&lt;br&gt;
The undoStack and the undoStackPointer: undoStack is a reference to an array that will store the history of state changes (patches) for undoable actions. undoStackPointer is a reference to a number that keeps track of the current position in the undo stack.&lt;br&gt;
The undoable parameter: A boolean flag indicating whether the action should be considered undoable&lt;br&gt;
Managing undo history: If the action is marked as undoable (undoable is true), the code adds the patches and inverse patches to the undoStack for potential undo operations.&lt;br&gt;
undoStackPointer is incremented to point to the current position in the stack.&lt;br&gt;
The previous undoable actions beyond the pointer are removed from the stack to maintain a linear history&lt;br&gt;
Overall, this code manages a history of state changes in an undo stack, allowing users to perform undoable actions on a set of "boxes" while maintaining the ability to revert those changes. The dispatch function updates the state and also manages the undo stack accordingly.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Buttons
&lt;/h3&gt;

&lt;p&gt;We would have 4 buttons in this application: Create - Delete - Undo - Redo. Let’s go into each of them:&lt;br&gt;
Create Button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const createButton = () =&amp;gt; {
    const width = Math.floor(Math.random() * (300 - 100 + 1) + 100)
    const height = Math.floor(Math.random() * (300 - 100 + 1) + 100)
    dispatch({
      type: "ADD_BOX",
      width: width,
      height: height,
      id: uuidv4(),
      color:
        `#` +
        Math.floor(16777215 * Math.random()).toString(16),
      position: {
        x: window.innerWidth * 0.8 / 2 - width / 2,
        y: window.innerHeight / 2 - height / 2,
      }
    });
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When crafting a fresh box, you'll observe that I've introduced randomness to its dimensions encompassing width and height, as well as imbuing it with a distinctive hue and a one-of-a-kind identifier. This newly generated box is thoughtfully positioned at the screen's center by skillfully manipulating the x-axis and y-axis coordinates. Ultimately, the culmination of these steps is manifested through the invocation of the aforesaid "dispatch" function, effectively bringing the envisioned creation to life.&lt;br&gt;
Delete Button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const deleteButton = () =&amp;gt; {
    dispatch({
      type: "DELETE",
    });
    dispatch({
      type: "SELECT_BOX",
      id: null
    }, false)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There isn't a great deal to elaborate on in this context; we simply initiate a dispatch action to delete, subsequently ensuring that the box is unselected.&lt;br&gt;
Undo and Redo buttons&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const undoButton = () =&amp;gt; {
    if (undoStackPointer.current &amp;lt; 0) return;
    const patches = undoStack.current[undoStackPointer.current].inversePatches;
    dispatch({ type: "APPLY_PATCHES", patches }, false);
    undoStackPointer.current--;
    dispatch({
      type: "SELECT_BOX",
      id: null
    }, false)
  };

  const redoButton = () =&amp;gt; {
    if (undoStackPointer.current === undoStack.current.length - 1) return;
    undoStackPointer.current++;
    const patches = undoStack.current[undoStackPointer.current].patches;
    dispatch({ type: "APPLY_PATCHES", patches }, false);
    dispatch({
      type: "SELECT_BOX",
      id: null
    }, false)
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I put these 2 functions together so you can see the contrasts. We won’t allow the users to be undoed if they are at the bottom of the stack, and won’t allow the users to redo if they are on top of the stack. Then we get the patches and apply it using the “APPLY_PATCHES” action. Remember to unselect the box to avoid bugs&lt;/p&gt;

&lt;h3&gt;
  
  
  The Results
&lt;/h3&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%2Fbz3mwahgvm7229d4xd1h.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%2Fbz3mwahgvm7229d4xd1h.gif" alt="Image description" width="600" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;By the end of this tutorial, you will not only have a firm grasp of how to implement time travel with Immer in React, but you will also possess a powerful debugging technique that can drastically improve your development workflow. Join us on this journey to unravel the secrets of time travel and revolutionize the way you approach debugging in React applications.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Enhance your TypeScript with Type Guards</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Wed, 03 Jul 2024 10:37:49 +0000</pubDate>
      <link>https://forem.com/starneit/enhance-your-typescript-with-type-guards-4jk6</link>
      <guid>https://forem.com/starneit/enhance-your-typescript-with-type-guards-4jk6</guid>
      <description>&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;The world of JavaScript development has been transformed by TypeScript's robust static typing abilities. Amidst its numerous attributes, type guards emerge as a potent instrument, enhancing the language's type safety significantly. This article embarks on an exploration of Type guards in TypeScript, delving into their intricacies, utilization, and indispensable contribution to fortifying code integrity and eliminating errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;

&lt;p&gt;Type guards in TypeScript are a set of techniques that allow developers to narrow down the type of a variable or expression within conditional blocks of code. They provide a way to perform runtime checks on the type of a value and refine the TypeScript type of that value accordingly.&lt;br&gt;
Type guards are particularly useful when dealing with union types, where a variable can have multiple possible types. By using type guards, developers can make more precise assumptions about the actual type of a value at runtime, enabling better type inference and enhanced type safety.&lt;br&gt;
Type guards can be implemented using various methods, such as checking for specific properties or using JavaScript runtime constructs like instanceof or typeof. These techniques help TypeScript's type system understand the changes in the type of a variable after a successful type check.&lt;/p&gt;
&lt;h3&gt;
  
  
  Examples and Usages
&lt;/h3&gt;

&lt;p&gt;Absolutely, let's go through each of the examples and their explanations:&lt;br&gt;
Typeof Type Guard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  function printLength(value: string | number): void {
     if (typeof value === "string") {
       console.log(value.length);
     } else {
       console.log("Value is not a string");
     }
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation: In this example, typeof value === "string" acts as a type guard. If the type of value is narrowed down to "string" within the if block, TypeScript understands that the length property can be safely accessed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Instanceof Type Guard:
  class Dog {
     bark() {
       console.log("Woof!");
     }
   }

   class Cat {
     meow() {
       console.log("Meow!");
     }
   }

   function makeSound(animal: Dog | Cat): void {
     if (animal instanceof Dog) {
       animal.bark();
     } else if (animal instanceof Cat) {
       animal.meow();
     }
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation: The instanceof operator is used as a type guard here. It narrows the type of animal to either Dog or Cat based on the condition. This allows TypeScript to determine which methods are accessible on the animal object.&lt;br&gt;
Custom User-Defined Type Guard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  interface Circle {
     kind: "circle";
     radius: number;
   }

   interface Square {
     kind: "square";
     sideLength: number;
   }

   type Shape = Circle | Square;

   function isCircle(shape: Shape): shape is Circle {
     return shape.kind === "circle";
   }

   function area(shape: Shape): number {
     if (isCircle(shape)) {
       return Math.PI * shape.radius ** 2;
     } else {
       return shape.sideLength ** 2;
     }
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation: This demonstrates a custom user-defined type guard (isCircle). The type of shape is narrowed to Circle if isCircle returns true, which allows safe access to the radius property.&lt;br&gt;
Key Existence Type Guard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  interface Person {
     name: string;
     age?: number;
   }

   function greet(person: Person): void {
     console.log(`Hello, ${person.name}!`);
     if ("age" in person) {
       console.log(`You are ${person.age} years old.`);
     }
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation: The in operator is used here as a type guard to check if the "age" property exists in the person object. If it does, TypeScript narrows the type of person to { name: string; age: number }.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Null and Undefined Type Guard:
  function printLength(value: string | null): void {
     if (value !== null) {
       console.log(value.length);
     } else {
       console.log("Value is null");
     }
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation: By checking value !== null, TypeScript narrows down the type of value to exclude null, allowing safe access to the length property.&lt;br&gt;
In all these examples, type guards enable TypeScript to intelligently narrow down the types of variables or expressions within conditional blocks, leading to more accurate type inference and safer coding practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In the TypeScript landscape, type guards serve as a pivotal tool that elevates the language's static typing prowess. By refining variable types within conditional contexts, type guards fortify code integrity and clarity.&lt;br&gt;
Through diverse examples, we've witnessed type guards empower decisions about data types at runtime. Whether through typeof, instanceof, or custom checks, each approach preemptively averts errors.&lt;br&gt;
Type guards stand as a shield against runtime mishaps, fostering error-free development. They embody the synergy between developers and TypeScript, culminating in reliable, scalable code.&lt;br&gt;
As you embrace type guards, you embark on a journey toward steadfast applications in the dynamic software realm.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Preventing side effect functions in Flutter</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Wed, 03 Jul 2024 10:35:30 +0000</pubDate>
      <link>https://forem.com/starneit/preventing-side-effect-functions-in-flutter-1e61</link>
      <guid>https://forem.com/starneit/preventing-side-effect-functions-in-flutter-1e61</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Throughout my programming journey, I've learned that writing clean, efficient, and maintainable code is crucial. When working with Flutter, it's essential to avoid side effect functions that can cause unexpected issues and make the code harder to understand. Join me as we dive into the importance of steering clear of side effects and learn how to create well-crafted and reliable Flutter applications.&lt;br&gt;
When composing a function, you're aware of its inputs, which are the parameters, and its output, which is the return value. Anything that goes beyond this and influences the world outside the function is considered a side effect.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void hello() {
    print('Hello!');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Printing something to the console constitutes a side effect since it impacts the world beyond the function. If you want to modify your function to eliminate side effects, you could rewrite it 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;String hello() {
     return 'Hello!';
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, there's nothing within the function body that impacts the external environment. You'll need to print the string to the console outside of the function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grasping Side Effects
&lt;/h3&gt;

&lt;p&gt;Side effects encompass any alterations happening outside the direct scope of a function or widget. Such changes can involve modifying state, executing network requests, carrying out I/O operations, accessing databases, or interacting with external services. Side effects can result in reduced predictability and make understanding your application's behavior challenging. Consequently, it's vital to use techniques that minimize side effects and ensure your app remains dependable and easy to maintain.&lt;br&gt;
While it's acceptable and sometimes necessary for certain functions to have side effects, functions without side effects are generally easier to handle and comprehend. You can trust them to perform exactly as anticipated since they consistently return the same output for a given input. Functions of this type are also referred to as pure functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adopt Reactive Programming:
&lt;/h3&gt;

&lt;p&gt;Reactive programming is an approach that emphasizes handling state changes in a clear and foreseeable way. In Flutter, multiple reactive programming libraries exist, including Provider, Riverpod, Bloc, and MobX. These libraries let you segregate business logic from the user interface, facilitating improved control over side effects. By confining side effects to particular components, you can make certain that alterations remain contained and predictable.&lt;br&gt;
Opt for the Suitable State Management Method:&lt;br&gt;
Picking the right state management strategy can substantially decrease the incidence of side effects. Flutter provides a range of state management libraries, each possessing unique benefits and strong points. Libraries such as Provider and Riverpod promote the utilization of unchangeable data structures and impose one-way data flow. By following these principles, you can avoid unexpected side effects and boost the predictability of your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leverage Async/Await and Futures:
&lt;/h3&gt;

&lt;p&gt;Asynchronous tasks are frequently found in Flutter applications, particularly when working with network requests, file operations, or animations. Dart, the programming language employed in Flutter, offers robust asynchronous programming capabilities, such as async/await and Futures. By using these mechanisms, you can manage asynchronous operations more effectively and prevent possible side effects. The async/await syntax makes writing asynchronous code easier by enabling you to compose asynchronous tasks in a more synchronous manner, enhancing code readability and maintainability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Restrict the Usage of Global Variables:
&lt;/h3&gt;

&lt;p&gt;Global variables can lead to side effects as they can be accessed and altered from any part of your application. It's recommended to limit their use and instead confine related data and functions within particular components. By narrowing the scope of variables, you decrease the likelihood of unwanted side effects and render your code more modular and testable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conduct Rigorous Testing:
&lt;/h3&gt;

&lt;p&gt;Testing is an essential part of any software development process, including Flutter. In-depth unit and integration testing can aid in identifying and preventing side effects in your application. Creating tests that encompass various situations and edge cases allows you to confirm the behavior of different components and ensure that side effects are managed properly. Automated tests serve as a safety measure, helping you detect regressions when making modifications and giving you confidence in your codebase's stability.&lt;br&gt;
Steering clear of side effects is vital for developing dependable and maintainable Flutter applications. By embracing a reactive programming style, using suitable state management libraries, taking advantage of async/await and Futures, minimizing global variables, carrying out extensive testing, applying design patterns and architectural principles, and using Flutter's built-in widgets and APIs, you can significantly decrease the presence of side effects in your codebase. Prioritizing the avoidance of side effects paves the way for more predictable, high-performing, and error-free Flutter applications, ensuring a pleasant user experience and long-lasting success.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In conclusion, avoiding side effects is essential for building reliable and maintainable Flutter applications. By incorporating best practices and techniques, you can significantly reduce the occurrence of side effects in your codebase and create more predictable and performant applications. Embrace reactive programming and choose the right state management libraries, such as Provider or Riverpod, to ensure a clean separation of concerns. Leverage Dart's powerful async/await and Futures constructs to handle asynchronous operations efficiently. Limit the usage of global variables, localizing the scope of variables to make your code more modular and testable.&lt;br&gt;
Furthermore, prioritize thorough testing, including unit and integration tests, to identify and prevent side effects, ensuring that your components behave as expected. By following these strategies and harnessing Flutter's built-in widgets and APIs, you'll create delightful user experiences and set your application up for long-term success. By consistently focusing on preventing side effects, you'll produce higher-quality, more stable, and easily maintainable codebases, ultimately leading to a positive impact on both the development process and user satisfaction.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Record in TypeScript: Unveiling Its Surprising Power</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Wed, 03 Jul 2024 10:23:00 +0000</pubDate>
      <link>https://forem.com/starneit/record-in-typescript-unveiling-its-surprising-power-508f</link>
      <guid>https://forem.com/starneit/record-in-typescript-unveiling-its-surprising-power-508f</guid>
      <description>&lt;h3&gt;
  
  
  Introduction:
&lt;/h3&gt;

&lt;p&gt;TypeScript, with its robust type system, continues to offer developers an array of features that enhance code quality, maintainability, and overall development experience. Among its lesser-known gems is the Record type, which often remains in the shadows compared to more frequently used types like string, number, and boolean. However, underestimating the potential of Record would be a mistake. In this article, we will delve into the depths of the Record type, uncovering its versatility and demonstrating how it can be harnessed to create more powerful and expressive code. Get ready to be amazed by the possibilities that Record brings to TypeScript development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the Basics of Record:
&lt;/h3&gt;

&lt;p&gt;At its core, the Record type is a built-in utility type in TypeScript that allows you to create an object with a known set of keys, each mapped to specific value types. Its syntax is quite straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type MyRecord = Record&amp;lt;KeyType, ValueType&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, KeyType represents the type of keys you want to map, and ValueType represents the type of values associated with those keys. This seemingly simple structure opens the door to a world of possibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leveraging Record for Type Safety:
&lt;/h3&gt;

&lt;p&gt;One of the key advantages of the Record type is its ability to provide type safety when dealing with dynamic data structures, like objects with varying key-value pairs. Suppose you are building an application that deals with user preferences, and each preference has a specific data type. With Record, you can ensure that each preference is associated with the correct data type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type UserPreferences = Record&amp;lt;string, string | number | boolean&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By utilizing Record, you create a structured way to define the shape of your preferences object, preventing errors that might arise from incorrect data types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expressive APIs with Record:
&lt;/h3&gt;

&lt;p&gt;Another remarkable aspect of Record lies in its capacity to define expressive APIs. Consider scenarios where you need to create a dictionary-like structure for managing different resources, such as translations for an internationalized app. With Record, you can elegantly define your resource dictionary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type ResourceDictionary = Record&amp;lt;string, string&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach not only enhances readability but also allows for easy additions or modifications of resources. Furthermore, Record can be combined with other TypeScript features, like mapped types and conditional types, to create even more sophisticated and precise APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Record for Advanced Data Transformations:
&lt;/h3&gt;

&lt;p&gt;The potential of Record goes beyond simple data structures. It's a powerful tool for advanced data transformations. For example, you can use Record in conjunction with mapped types to transform an array of objects into a dictionary-like structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type TransformArrayToDictionary&amp;lt;T extends { id: string }&amp;gt; = Record&amp;lt;T['id'], T&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This transformation allows you to access objects directly using their unique IDs, resulting in optimized data retrieval.&lt;/p&gt;

&lt;h3&gt;
  
  
  Potential Pitfall
&lt;/h3&gt;

&lt;p&gt;When using the Record type in TypeScript, it's important to be aware of a potential pitfall that can lead to unintended behavior and unexpected results. While the Record type is powerful and versatile, it has a behavior related to the assignment of properties that might catch developers off guard.&lt;br&gt;
The issue arises from the fact that TypeScript's Record type allows any string key to be associated with a certain value type. This means that you can easily assign properties to a Record object without restriction. However, this behavior can lead to situations where you inadvertently assign properties that might not be part of the intended data structure.&lt;br&gt;
For example, consider the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type UserPreferences = Record&amp;lt;string, string | number | boolean&amp;gt;;

const preferences: UserPreferences = {
  theme: 'dark',
  fontSize: 16,
  // Mistake: Incorrect property name
  colorScheme: 'light', // Oops!
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the developer might have intended to define only theme and fontSize preferences. However, due to the permissive nature of the Record type, the assignment of the colorScheme property goes unnoticed. This can lead to runtime errors or unexpected behavior when accessing or using the preferences object.&lt;br&gt;
To mitigate this risk, it's recommended to use more specific types or interfaces whenever possible, rather than relying solely on the Record type. By using specific types, you can define a clear structure for your data objects and avoid accidental assignments of unexpected properties.&lt;br&gt;
If you do choose to use the Record type, make sure to carefully manage and document the allowed property names to prevent unintended assignments. Additionally, TypeScript's strict type checking can help catch such mistakes during development, so ensuring that you have enabled strict mode in your TypeScript configuration is beneficial.&lt;br&gt;
In summary, while the Record type is a useful tool, it's crucial to be cautious and vigilant when using it to avoid potential pitfalls related to assigning unintended properties. Using more specific types or interfaces whenever possible can help enhance type safety and prevent unexpected issues in your TypeScript code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion:
&lt;/h3&gt;

&lt;p&gt;The Record type in TypeScript might seem humble at first glance, but its capabilities are far-reaching and impactful. By leveraging Record, you can enforce type safety, create expressive APIs, and perform complex data transformations with elegance and confidence. As you continue your TypeScript journey, don't overlook the power of Record; it's a tool that can significantly elevate your code quality and development experience. Embrace the potential of Record, and explore the numerous ways it can empower your TypeScript projects to new heights.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Single Page Application: Authentication and Authorization in Angular</title>
      <dc:creator>Senior Developer</dc:creator>
      <pubDate>Wed, 03 Jul 2024 09:54:43 +0000</pubDate>
      <link>https://forem.com/starneit/single-page-application-authentication-and-authorization-in-angular-118b</link>
      <guid>https://forem.com/starneit/single-page-application-authentication-and-authorization-in-angular-118b</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In a Single Page Application (SPA), each element has its own existence and lifecycle, rather than being part of a global page state. Authentication and authorization can affect some or all elements on the screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication Process in an SPA
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;User login: Obtain an access and refresh token.&lt;/li&gt;
&lt;li&gt;Client-side storage: Store tokens and minimal details in local storage.&lt;/li&gt;
&lt;li&gt;Login resolver: Redirect away from the login page if the user is authenticated.&lt;/li&gt;
&lt;li&gt;Router auth guard: Redirect to the login page if the user is unauthenticated.&lt;/li&gt;
&lt;li&gt;Logout: Remove stored data.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Additional Considerations
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;HTTP interceptor: Use the token for API calls.&lt;/li&gt;
&lt;li&gt;401 handling: Request a new token when necessary.&lt;/li&gt;
&lt;li&gt;User display: Retrieve and display user details on the screen.&lt;/li&gt;
&lt;li&gt;Redirect URL: Track additional information.&lt;/li&gt;
&lt;li&gt;Other concerns include third-party adaptation and server-side rendering for obtaining access tokens.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Basic Login Example
&lt;/h3&gt;

&lt;p&gt;Begin with a simple authentication form that requires a username and password. The API accepts the credentials and returns an access token and refresh token.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Auth service
@Injectable({ providedIn: 'root' })
export class AuthService {
  private _loginUrl = '/auth/login';
  constructor(private _http: HttpClient) {}
  // login method
  Login(username: string, password: string): Observable&amp;lt;any&amp;gt; {
    return this._http.post(this._loginUrl, { username, password }).pipe(
      map((response) =&amp;gt; {
        // prepare the response to be handled, then return
        return response;
      })
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the login is successful, save the information in localStorage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Login(username: string, password: string): Observable&amp;lt;any&amp;gt; {
  return this._http.post(this._loginUrl, { username, password }).pipe(
    map((response) =&amp;gt; {
      const retUser: IAuthInfo = &amp;lt;IAuthInfo&amp;gt;(&amp;lt;any&amp;gt;response).data;
      // save in localStorage
      localStorage.setItem('user', JSON.stringify(retUser));
      return retUser;
    })
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon revisiting the site, user information should be populated from localStorage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Auth State Management
&lt;/h3&gt;

&lt;p&gt;To manage the authentication state, use RxJS BehaviorSubject and Observable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Auth service
export class AuthService {
  // create an internal subject and an observable to keep track
  private stateItem: BehaviorSubject&amp;lt;IAuthInfo | null&amp;gt; = new BehaviorSubject(null);
  stateItem$: Observable&amp;lt;IAuthInfo | null&amp;gt; = this.stateItem.asObservable();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling User Status
&lt;/h3&gt;

&lt;p&gt;If the localStorage status indicates the user is logged in and the page is refreshed, the user should be redirected to the appropriate location.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logout Process
&lt;/h3&gt;

&lt;p&gt;To log out, remove the state and localStorage data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// services/auth.service
Logout() {
  this.RemoveState();
  localStorage.removeItem(ConfigService.Config.Auth.userAccessKey);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Auth Guard
&lt;/h3&gt;

&lt;p&gt;To protect private routes and redirect unauthorized users, use an AuthGuard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// services/auth.guard
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate, CanActivateChild {
    constructor(private authState: AuthService, private _router: Router) {}

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable&amp;lt;boolean&amp;gt; {
      return this.secure(route);
    }

    canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable&amp;lt;boolean&amp;gt; {
      return this.secure(route);
    }

    private secure(route: ActivatedRouteSnapshot | Route): Observable&amp;lt;boolean&amp;gt; {
      return this.authState.stateItem$.pipe(
         map(user =&amp;gt; {
            if (!user) {
               this._router.navigateByUrl('/login');
               return false;
            }
            // user exists
            return true;
         })
      );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Use Cases
&lt;/h3&gt;

&lt;p&gt;In future iterations, the access token can be used for API calls, and handling a 401 error can be implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP Interceptor
&lt;/h3&gt;

&lt;p&gt;To automatically add the access token to API calls, use an HTTP interceptor. This will help manage authentication headers for all requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// services/auth.interceptor.ts
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private authService: AuthService) {}

  intercept(req: HttpRequest&amp;lt;any&amp;gt;, next: HttpHandler): Observable&amp;lt;HttpEvent&amp;lt;any&amp;gt;&amp;gt; {
    const authToken = this.authService.getAccessToken();

    if (authToken) {
      const authReq = req.clone({
        headers: req.headers.set('Authorization', 'Bearer ' + authToken),
      });
      return next.handle(authReq);
    } else {
      return next.handle(req);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register the interceptor in the app.module.ts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app.module.ts
@NgModule({
  // ...
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi: true,
    },
  ],
})
export class AppModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling 401 Errors
&lt;/h3&gt;

&lt;p&gt;To handle 401 errors, create another interceptor that detects the error and refreshes the access token if necessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// services/error.interceptor.ts
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
  constructor(private authService: AuthService, private router: Router) {}

  intercept(req: HttpRequest&amp;lt;any&amp;gt;, next: HttpHandler): Observable&amp;lt;HttpEvent&amp;lt;any&amp;gt;&amp;gt; {
    return next.handle(req).pipe(
      catchError((error: HttpErrorResponse) =&amp;gt; {
        if (error.status === 401) {
          // Refresh the access token and retry the request.
          return this.authService.refreshAccessToken().pipe(
            switchMap((newToken) =&amp;gt; {
              const authReq = req.clone({
                headers: req.headers.set('Authorization', 'Bearer ' + newToken),
              });
              return next.handle(authReq);
            })
          );
        } else {
          return throwError(error);
        }
      })
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register the error interceptor in the &lt;code&gt;app.module.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app.module.ts
@NgModule({
  // ...
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: ErrorInterceptor,
      multi: true,
    },
  ],
})
export class AppModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  User Display
&lt;/h3&gt;

&lt;p&gt;To display user information, create a component that subscribes to the &lt;code&gt;authService.stateItem$&lt;/code&gt; Observable and updates the UI accordingly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// components/user-display/user-display.component.ts
@Component({
  selector: 'app-user-display',
  templateUrl: './user-display.component.html',
  styleUrls: ['./user-display.component.scss'],
})
export class UserDisplayComponent implements OnInit {
  user$: Observable&amp;lt;IUser&amp;gt;;

  constructor(private authService: AuthService) {}

  ngOnInit(): void {
    this.user$ = this.authService.stateItem$.pipe(map((state) =&amp;gt; state?.payload));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Include this component wherever it is needed to display user information.&lt;/p&gt;

&lt;p&gt;Redirect URL&lt;br&gt;
To redirect users to the original URL they were attempting to access before being redirected to the login page, store the URL during the authentication process.&lt;/p&gt;

&lt;p&gt;Update the AuthGuard to save the attempted URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// services/auth.guard.ts
private secure(route: ActivatedRouteSnapshot | Route): Observable&amp;lt;boolean&amp;gt; {
  return this.authState.stateItem$.pipe(
    map((user) =&amp;gt; {
      if (!user) {
        // Save the attempted URL
        this.authService.setRedirectUrl(route.url);
        this._router.navigateByUrl('/login');
        return false;
      }
      return true;
    })
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add methods to the AuthService to store and retrieve the redirect URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// services/auth.service.ts
private redirectUrl: string;

setRedirectUrl(url: string) {
  this.redirectUrl = url;
}

getRedirectUrl(): string {
  return this.redirectUrl;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify the login component to redirect the user to the stored URL upon successful login:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// login component
login() {
  this.authService.Login('username', 'password').subscribe({
    next: (result) =&amp;gt; {
      const redirectUrl = this.authService.getRedirectUrl();

      if (redirectUrl) {
        this.router.navigateByUrl(redirectUrl);
      } else {
        this.router.navigateByUrl('/private/dashboard');
      }
    },
    // ...
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will ensure that users are taken back to the original URL they attempted to access after logging in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Third-Party Authentication
&lt;/h3&gt;

&lt;p&gt;To integrate third-party authentication providers, such as Google or Facebook, follow these general steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Register your application with the third-party provider and obtain the required credentials (client ID and secret).&lt;/li&gt;
&lt;li&gt;Implement a "Login with [Provider]" button in your login component that redirects users to the provider's authentication page.&lt;/li&gt;
&lt;li&gt;Create an endpoint in your backend to handle the authentication response and exchange the authorization code for an access token.&lt;/li&gt;
&lt;li&gt;Save the third-party access token in your database and return a custom access token (JWT) to your SPA.&lt;/li&gt;
&lt;li&gt;Adapt your AuthService to handle third-party authentication and store the received JWT.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Server-Side Rendering (SSR)
&lt;/h3&gt;

&lt;p&gt;If your application uses server-side rendering, you'll need to handle the initial authentication state differently. In this case, the access token can be fetched during the SSR process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In your server-side rendering logic, check for the access token in cookies or local storage.&lt;/li&gt;
&lt;li&gt;If an access token is found, include it in the initial state of your application.&lt;/li&gt;
&lt;li&gt;In your AuthService, use the APP_INITIALIZER to read the access token from the initial state instead of local storage.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Token Refresh
&lt;/h3&gt;

&lt;p&gt;For better security, your application should implement token refresh logic. When the access token expires, the application should use the refresh token to request a new access token without requiring the user to log in again.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a method in the AuthService to request a new access token using the refresh token.&lt;/li&gt;
&lt;li&gt;Update the ErrorInterceptor to call the refresh token method when a 401 status is encountered.&lt;/li&gt;
&lt;li&gt;Store the new access token and update the authentication state.&lt;/li&gt;
&lt;li&gt;Retry the original API call with the new access token.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Roles and Permissions
&lt;/h3&gt;

&lt;p&gt;To further enhance the authorization process, you can implement role-based access control using roles and permissions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Assign roles and permissions to users during the registration or login process.&lt;/li&gt;
&lt;li&gt;Include the user's roles and permissions in the JWT payload.&lt;/li&gt;
&lt;li&gt;Create a custom AuthRoleGuard that checks for the required roles and permissions in the JWT before granting access.&lt;/li&gt;
&lt;li&gt;Protect routes using the AuthRoleGuard based on the roles and permissions required.
By implementing these additional features, you can create a robust and secure authentication and authorization system for your Single Page Application.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In conclusion, adding a login system to a website makes it safer and easier to use. We talked about many steps like logging in, saving information, and making sure only the right people can see certain things. We also discussed some cool extra features, like using other websites to log in or giving different people different permissions. Following these steps will help create a cool and safe website that everyone enjoys using. Keep learning and improving your website over time!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
