<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Shlomi's blog]]></title><description><![CDATA[Shlomi's blog]]></description><link>https://blog.shlomisela.com</link><generator>RSS for Node</generator><lastBuildDate>Sun, 10 May 2026 08:01:26 GMT</lastBuildDate><atom:link href="https://blog.shlomisela.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Moving Beyond JSX: Why TSRX Caught My Eye]]></title><description><![CDATA[It’s been a minute since I posted here, but I recently stumbled across a project that genuinely made me stop and rethink how we write frontend code: TSRX (TypeScript Render Extensions).
If you work wi]]></description><link>https://blog.shlomisela.com/moving-beyond-jsx-why-tsrx-caught-my-eye</link><guid isPermaLink="true">https://blog.shlomisela.com/moving-beyond-jsx-why-tsrx-caught-my-eye</guid><dc:creator><![CDATA[Shlomi Sela]]></dc:creator><pubDate>Sat, 02 May 2026 09:42:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/65e9f54823ffb71248482745/defca564-72d0-4c62-a9f2-7155ba528a80.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It’s been a minute since I posted here, but I recently stumbled across a project that genuinely made me stop and rethink how we write frontend code: TSRX (TypeScript Render Extensions).</p>
<p>If you work with React, JSX is practically second nature. We’ve all accepted its quirks as the cost of doing business. But let's be honest-after years of writing it, the cracks in the JSX developer experience are pretty obvious. TSRX feels like the exact upgrade to JSX we didn't know we were waiting for.</p>
<p>Here is why it stands out when you put it side-by-side with standard JSX:</p>
<p><strong>1. The End of "Ternary Hell" (Native Control Flow)</strong> This is probably the biggest daily friction point in JSX. Because JSX forces everything inside the template to be an expression, we can't use native JavaScript statements.</p>
<p><strong>The JSX Way:</strong> You want to conditionally render something? You're stuck writing nested ternary operators (<code>condition ? &lt;A/&gt; : &lt;B/&gt;</code>) or chaining logical ANDs (<code>&amp;&amp;</code>). Need to render a list? You have to map over arrays inline (<code>items.map(...)</code>), often leading to messy, hard-to-read "JSX soup."</p>
<pre><code class="language-typescript">// The JSX Way
return (
  &lt;div&gt;
    {isLoading ? (
      &lt;Spinner /&gt;
    ) : (
      &lt;div&gt;
        {items.length &gt; 0 &amp;&amp; (
          &lt;ul&gt;
            {items.map(item =&gt; (
              &lt;li key={item.id}&gt;{item.name}&lt;/li&gt;
            ))}
          &lt;/ul&gt;
        )}
      &lt;/div&gt;
    )}
  &lt;/div&gt;
);
</code></pre>
<p><strong>The TSRX Way:</strong> You just write normal code. You can use standard <code>if</code>, <code>else</code>, <code>switch</code>, and <code>for</code> statements directly inside your markup. The mental overhead of translating logic into expressions simply disappears. It looks and reads like standard programming.</p>
<pre><code class="language-typescript">// The TSRX Way
return (
  &lt;div&gt;
    {if (isLoading) {
      &lt;Spinner /&gt;
    } else {
      &lt;div&gt;
        {if (items.length &gt; 0) {
          &lt;ul&gt;
            {for (const item of items) {
              &lt;li key={item.id}&gt;{item.name}&lt;/li&gt;
            }}
          &lt;/ul&gt;
        }}
      &lt;/div&gt;
    }}
  &lt;/div&gt;
);
</code></pre>
<p><strong>2. Solving the "Rules of Hooks" Headache</strong> We all know the golden rule of React: <em>Don't call Hooks conditionally.</em></p>
<p><strong>The JSX Way:</strong> If you need a hook that only runs under certain conditions, you are forced to extract that logic into a brand new, artificially created sub-component. It fragments your codebase and forces you to context-switch just to satisfy the linter.</p>
<pre><code class="language-typescript">// The JSX Way
// You have to create a dedicated wrapper component just to use the hook conditionally
function DetailsWrapper({ id }) {
  const details = useDetails(id);
  return &lt;Details data={details} /&gt;;
}

// Inside the parent component:
{showDetails &amp;&amp; &lt;DetailsWrapper id={id} /&gt;}
</code></pre>
<p><strong>The TSRX Way:</strong> TSRX uses a smart compiler. If you write an <code>if</code> block and place a Hook inside it, the TSRX compiler handles the heavy lifting behind the scenes, automatically extracting that block into a separate component during the build process. You get the DX of inline conditionals without breaking React's rules.</p>
<pre><code class="language-typescript">// The TSRX Way
// Just use the hook inside the condition. The compiler handles the extraction!
{if (showDetails) {
  const details = useDetails(id);
  &lt;Details data={details} /&gt;
}}
</code></pre>
<p><strong>3. True Co-location (Variables Exactly Where You Need Them)</strong></p>
<p><strong>The JSX Way:</strong> If you need to calculate a derived variable for a specific piece of UI, you have to define it at the top of your component, far away from where it's actually used in the return statement.</p>
<pre><code class="language-typescript">// The JSX Way
function Product({ price, discount }) {
  // Declared way up here, far from the actual UI
  const discountPrice = price - (price * discount);

  return (
    &lt;div&gt;
      {/* ... lots of other UI components ... */}
      &lt;div className="price-tag"&gt;
        ${discountPrice}
      &lt;/div&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p><strong>The TSRX Way:</strong> You can declare block-scoped variables (<code>let</code> or <code>const</code>) right inside your markup blocks. Your logic, structure, and styling live intimately together.</p>
<pre><code class="language-typescript">// The TSRX Way
function Product({ price, discount }) {
  return (
    &lt;div&gt;
      {/* ... lots of other UI components ... */}
      {
        // Declared exactly where it is used
        const discountPrice = price - (price * discount);
        &lt;div className="price-tag"&gt;
          ${discountPrice}
        &lt;/div&gt;
      }
    &lt;/div&gt;
  );
}
</code></pre>
<p><strong>4. A Better Fit for Agents</strong> This structural clarity isn't just great for us; it's a massive win for the way we build software today. When we use Agents like Cursor or Claude to help write or refactor code, context fragmentation is the enemy. Because TSRX reduces the need to artificially split components and keeps logic natively readable, Agents can better understand the component's flow. The resulting code is easier to prompt and generate, and much less prone to AI-induced bugs.</p>
<p><strong>The Verdict</strong> TSRX is still in Alpha, so keep it out of your production environments for now. But it compiles down to React, Preact, Solid, or Vue, ships with a solid VS Code extension, and can live side-by-side with your existing <code>.tsx</code> files.</p>
<p>It’s rare to see a tool that fundamentally challenges the way we write templates while actually improving readability. Check out the docs and give it a run locally-it might just change how you look at JSX.</p>
]]></content:encoded></item><item><title><![CDATA[Mastering Flow-Relative CSS for Internationalization: A Deep Dive]]></title><description><![CDATA[The world of web development is continuously evolving, and a significant part of this evolution is the shift towards more inclusive and flexible design practices. Flow-relative CSS, rooted in the CSS Logical Properties and Values Level 1, is at the f...]]></description><link>https://blog.shlomisela.com/mastering-flow-relative-css-for-internationalization-a-deep-dive</link><guid isPermaLink="true">https://blog.shlomisela.com/mastering-flow-relative-css-for-internationalization-a-deep-dive</guid><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[CSS]]></category><category><![CDATA[CSS3]]></category><category><![CDATA[internationalization]]></category><category><![CDATA[UI]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><dc:creator><![CDATA[Shlomi Sela]]></dc:creator><pubDate>Sat, 09 Mar 2024 16:00:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709999943989/99cc7c9e-92f6-43d1-9ef3-2ca5576a7e0a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The world of web development is continuously evolving, and a significant part of this evolution is the shift towards more inclusive and flexible design practices. Flow-relative CSS, rooted in the CSS Logical Properties and Values Level 1, is at the forefront of this shift, offering a more adaptable approach to handling text directionality in web design.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>Traditionally, CSS has been heavily reliant on physical direction properties (like <code>margin-left</code> or <code>margin-right</code>) which are inherently tied to the layout direction. This approach poses challenges in internationalization, especially when designing for languages that use right-to-left (RTL) scripts like Arabic or Hebrew. Flow-relative properties, such as <code>margin-inline-start</code> and <code>padding-inline-end</code>, offer a solution by abstracting the directionality, making styles adaptable to both LTR and RTL layouts without the need for redundant code.</p>
<h2 id="heading-understanding-flow-relative-properties">Understanding Flow-Relative Properties</h2>
<p>Flow-relative CSS properties are based on the flow of the content rather than the physical dimensions of the screen. They are divided into two categories:</p>
<ul>
<li><strong>Inline Properties</strong>: These relate to the layout in the inline direction (left-to-right in LTR scripts, right-to-left in RTL scripts). Examples include <code>margin-inline-start</code> and <code>padding-inline-end</code>.</li>
<li><strong>Block Properties</strong>: These apply in the block direction (top-to-bottom in most scripts). Examples include <code>margin-block-start</code> and <code>margin-block-end</code>.
The key advantage here is the abstraction of layout direction, making your CSS more flexible and context-aware.</li>
</ul>
<h2 id="heading-advantages-of-flow-relative-css">Advantages of Flow-Relative CSS</h2>
<h3 id="heading-enhanced-internationalization">Enhanced Internationalization</h3>
<p>Flow-relative properties automatically adjust to the writing mode, significantly simplifying the creation of layouts that work seamlessly in both LTR and RTL contexts. This is invaluable for websites that aim for a global audience.</p>
<h3 id="heading-code-efficiency-and-maintenance">Code Efficiency and Maintenance</h3>
<p>By using Flow-Relative properties, you can significantly reduce the duplication of style rules for LTR and RTL layouts, leading to a cleaner, more maintainable codebase.</p>
<h3 id="heading-flexibility-and-scalability">Flexibility and Scalability</h3>
<p>These properties make your stylesheets more adaptable and ready for a variety of languages and scripts, supporting the global nature of the web.</p>
<h2 id="heading-implementing-flow-relative-properties">Implementing Flow-Relative Properties</h2>
<p>Let's explore how to implement these properties in practice. Consider a scenario where you need to apply a margin to the start of an element:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Traditional Approach */</span>
<span class="hljs-selector-class">.ltr</span> <span class="hljs-selector-class">.example</span> {
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">1.25rem</span>; <span class="hljs-comment">/* Left margin for LTR */</span>
}
<span class="hljs-selector-class">.rtl</span> <span class="hljs-selector-class">.example</span> {
  <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">1.25rem</span>; <span class="hljs-comment">/* Right margin for RTL */</span>
}

<span class="hljs-comment">/* Flow-Relative Approach */</span>
<span class="hljs-selector-class">.example</span> {
  <span class="hljs-attribute">margin-inline-start</span>: <span class="hljs-number">1.25rem</span>; <span class="hljs-comment">/* Start margin for both LTR and RTL */</span>
}
</code></pre>
<p>In the Flow-Relative approach, <code>margin-inline-start</code> intelligently applies the margin to the start of the element, irrespective of the text direction.</p>
<h2 id="heading-complex-layouts-and-responsive-design">Complex Layouts and Responsive Design</h2>
<p>In more complex and responsive layouts, Flow-Relative properties can be combined with media queries and other responsive design techniques. This ensures that your layouts remain adaptable and responsive, not just to screen sizes but also to different writing modes.</p>
<h2 id="heading-challenges-and-solutions">Challenges and Solutions</h2>
<p>Transitioning to Flow-Relative CSS might require some initial adjustment, particularly if you're used to thinking in terms of physical directions. However, the benefits in terms of internationalization and maintainability are well worth the effort. Start by experimenting with these properties in smaller modules or components, gradually integrating them into your broader styling practices.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Flow-relative CSS is more than just a set of new properties; it represents a paradigm shift in CSS toward more inclusive and adaptable web design. By embracing these properties, developers can create websites that are truly global and accessible, without compromising on efficiency or maintainability.</p>
<h2 id="heading-further-reading">Further Reading</h2>
<p>To deepen your understanding of Flow-Relative CSS, refer to the <a target="_blank" href="https://drafts.csswg.org/css-logical/">CSS Logical Properties and Values Level 1</a>, and explore resources like MDN Web Docs for practical examples and guidance.</p>
]]></content:encoded></item><item><title><![CDATA[Simplifying Data Fetching in React with SWR: A Quick Guide]]></title><description><![CDATA[Modern React applications often require real-time data fetching, caching, and synchronization, which can be challenging. SWR, developed by Vercel, simplifies this process significantly. This article explores how to harness the power of SWR to improve...]]></description><link>https://blog.shlomisela.com/simplifying-data-fetching-in-react-with-swr-a-quick-guide</link><guid isPermaLink="true">https://blog.shlomisela.com/simplifying-data-fetching-in-react-with-swr-a-quick-guide</guid><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Shlomi Sela]]></dc:creator><pubDate>Fri, 08 Mar 2024 08:47:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709887599041/5c4bb4ec-1340-4324-ac00-6abd7156d461.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Modern React applications often require real-time data fetching, caching, and synchronization, which can be challenging. SWR, developed by Vercel, simplifies this process significantly. This article explores how to harness the power of SWR to improve data fetching in React.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>Fetching data in React applications can be complex, involving managing states for loading, data, and errors. SWR (Stale-While-Revalidate) provides a streamlined approach to handle these concerns elegantly.</p>
<h2 id="heading-what-is-swr">What is SWR?</h2>
<p>SWR is a React Hooks library for data fetching. The name derives from the HTTP cache invalidation strategy (stale-while-revalidate) which effectively means "serve the stale (old) data until you get a chance to validate (fetch the latest data)."</p>
<h2 id="heading-key-features-of-swr">Key Features of SWR</h2>
<p>SWR brings several advantages:</p>
<ul>
<li><strong>Built-in Cache and State Management</strong>: Automatically caches fetched data and manages the loading and error states.</li>
<li><strong>Real-time Experience</strong>: Offers features like automatic revalidation on focus, network recovery, and interval polling.</li>
<li><strong>Lightweight and Flexible</strong>: Easy to integrate and use in existing projects with minimal configuration.</li>
</ul>
<h2 id="heading-getting-started-with-swr">Getting Started with SWR</h2>
<p>To start using SWR, first install it:</p>
<pre><code class="lang-bash">npm install swr
</code></pre>
<p>Then, you can use the useSWR hook to fetch data:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> useSWR <span class="hljs-keyword">from</span> <span class="hljs-string">'swr'</span>;

<span class="hljs-keyword">const</span> fetcher = <span class="hljs-function"><span class="hljs-params">url</span> =&gt;</span> fetch(url).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json());

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserProfile</span>(<span class="hljs-params">{ userId }</span>) </span>{
  <span class="hljs-keyword">const</span> { data, error } = useSWR(<span class="hljs-string">`/api/user/<span class="hljs-subst">${userId}</span>`</span>, fetcher);

  <span class="hljs-comment">// Handle loading and error states</span>
}
</code></pre>
<h2 id="heading-advanced-usage">Advanced Usage</h2>
<p>SWR also supports more advanced features like:</p>
<ul>
<li><strong>Conditional Fetching</strong>: Only fetch data when certain conditions are met.</li>
<li><strong>Dependent Fetching</strong>: Chain requests and fetches data only after certain data is available.</li>
<li><strong>Global Configuration</strong>: Customize SWR's behavior globally in your application.</li>
</ul>
<h2 id="heading-real-world-scenarios">Real-World Scenarios</h2>
<p>In a complex application, SWR can simplify data management. For example, in a dashboard application, SWR can handle multiple API requests, cache the data, and refresh it periodically, ensuring the user always sees up-to-date information.</p>
<h2 id="heading-best-practices-and-performance-optimization">Best Practices and Performance Optimization</h2>
<p>To maximize the benefits of SWR:</p>
<ul>
<li><strong>Optimize Fetcher Functions</strong>: Ensure your fetcher function is optimized and handles errors gracefully.</li>
<li><strong>Manage Cache Properly</strong>: Utilize SWR's cache management features to synchronize data across components.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>SWR offers a modern solution to the challenges of data fetching in React. It ensures efficient data management, leading to cleaner code and a better user experience.</p>
<h2 id="heading-further-resources">Further Resources</h2>
<p>For more information, check out:</p>
<ul>
<li><a target="_blank" href="https://swr.vercel.app/docs/">SWR Documentation</a></li>
<li><a target="_blank" href="https://github.com/vercel/swr">GitHub Repository</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Mastering React with SOLID Principles: A Practical Guide]]></title><description><![CDATA[React's component-based architecture makes it an excellent framework to apply SOLID principles. 
These principles enhance scalability, maintainability, and robustness in applications. 
This article focuses on implementing SOLID principles in React, s...]]></description><link>https://blog.shlomisela.com/mastering-react-with-solid-principles-a-practical-guide</link><guid isPermaLink="true">https://blog.shlomisela.com/mastering-react-with-solid-principles-a-practical-guide</guid><category><![CDATA[React]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Shlomi Sela]]></dc:creator><pubDate>Fri, 08 Mar 2024 08:45:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709887519075/5ad65677-4c48-41ec-90c7-5e77da3c5568.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>React's component-based architecture makes it an excellent framework to apply SOLID principles. 
These principles enhance scalability, maintainability, and robustness in applications. 
This article focuses on implementing SOLID principles in React, specifically using hooks.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>SOLID principles are crucial for creating high-quality code. They make your code extendable, logical, and easier to understand, which is especially beneficial in a flexible framework like React.</p>
<h2 id="heading-s-single-responsibility-principle-srp">S - Single Responsibility Principle (SRP)</h2>
<p><strong>Principle</strong>: A component should have one, and only one, reason to change.</p>
<p><strong>Example</strong>: 
Create functional components that handle a single functionality. For example, a <code>UserList</code> component should solely display users, not fetch user data.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> UserList = <span class="hljs-function">(<span class="hljs-params">{ users }</span>) =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {users.map(user =&gt; <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{user.id}</span>&gt;</span>{user.name}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>)}
  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
);
</code></pre>
<h2 id="heading-o-openclosed-principle">O - Open/Closed Principle</h2>
<p><strong>Principle</strong>: Components should be open for extension but closed for modification.</p>
<p><strong>Example</strong>: Utilize custom hooks to add functionality to a component without altering its core logic.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> useUserData = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [userData, setUserData] = useState(<span class="hljs-literal">null</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Fetch and set user data</span>
  }, []);

  <span class="hljs-keyword">return</span> userData;
};

<span class="hljs-keyword">const</span> UserProfile = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> userData = useUserData();
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{userData.name}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
};
</code></pre>
<h2 id="heading-l-liskov-substitution-principle-lsp">L - Liskov Substitution Principle (LSP)</h2>
<p><strong>Principle</strong>: Components should be replaceable with their subtypes.</p>
<p><strong>Example</strong>: Design components that can accept varying props but maintain the same interface.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> Button = <span class="hljs-function">(<span class="hljs-params">{ onClick, children }</span>) =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onClick}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
);

<span class="hljs-keyword">const</span> LinkButton = <span class="hljs-function">(<span class="hljs-params">{ href, children }</span>) =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">{href}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>
);
</code></pre>
<h2 id="heading-i-interface-segregation-principle-isp">I - Interface Segregation Principle (ISP)</h2>
<p><strong>Principle</strong>: Components should not be forced to depend on interfaces they do not use.</p>
<p><strong>Example</strong>: Create smaller, focused components instead of large, complex ones.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> UserName = <span class="hljs-function">(<span class="hljs-params">{ user }</span>) =&gt;</span> (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{user.name}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>);
<span class="hljs-keyword">const</span> UserPosts = <span class="hljs-function">(<span class="hljs-params">{ posts }</span>) =&gt;</span> (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{/* Post list */}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>);
</code></pre>
<h2 id="heading-d-dependency-inversion-principle-dip">D - Dependency Inversion Principle (DIP)</h2>
<p><strong>Principle</strong>: Depend on abstractions, not on concretions.</p>
<p><strong>Example: Employ context API to manage dependencies, keeping components decoupled.
</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> UserContext = React.createContext();

<span class="hljs-keyword">const</span> UserProfile = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> user = useContext(UserContext);
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{user.name}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
};

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{currentUser}</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">UserProfile</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">UserContext.Provider</span>&gt;</span></span>
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Implementing SOLID principles with React hooks leads to more efficient, maintainable, and scalable code. These practices set a strong foundation for building robust React applications.</p>
<h2 id="heading-further-reading-and-resources">Further Reading and Resources</h2>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/solid-principles-explained-in-plain-english/">The SOLID Principles of Object-Oriented Programming Explained in Plain English
</a></li>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/SOLID">SOLID - WikiPedia</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Unlocking Performance with Concurrent Rendering in React 18]]></title><description><![CDATA[React 18 introduces an exciting new feature: Concurrent Rendering. This article takes a deep dive into what Concurrent Rendering is, its benefits, and how it represents a significant shift from the traditional synchronous rendering approach in React....]]></description><link>https://blog.shlomisela.com/unlocking-performance-with-concurrent-rendering-in-react-18</link><guid isPermaLink="true">https://blog.shlomisela.com/unlocking-performance-with-concurrent-rendering-in-react-18</guid><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[React]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Shlomi Sela]]></dc:creator><pubDate>Fri, 08 Mar 2024 08:43:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709887353088/2b26da35-f302-412b-b6e3-d25ed4d7dac9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>React 18 introduces an exciting new feature: Concurrent Rendering. This article takes a deep dive into what Concurrent Rendering is, its benefits, and how it represents a significant shift from the traditional synchronous rendering approach in React.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>Concurrent Rendering is a powerful feature in React 18 that allows for multiple rendering tasks to happen without blocking the user interface. This marks a significant improvement in the way React handles rendering, leading to smoother user experiences and better application performance.</p>
<h2 id="heading-what-is-concurrent-rendering">What is Concurrent Rendering?</h2>
<p>Concurrent Rendering in React 18 enables the rendering of multiple elements in the background, at their own pace, without blocking the main thread. This means React can prepare new views in the background, interrupt rendering if higher-priority updates come in, and efficiently update the UI.</p>
<h2 id="heading-benefits-of-concurrent-rendering">Benefits of Concurrent Rendering</h2>
<ol>
<li><strong>Improved User Experience</strong>: By reducing the time spent on blocking the main thread, Concurrent Rendering ensures smoother interactions.</li>
<li><strong>Enhanced Performance</strong>: It enables React to work on high-priority updates first, improving the perceived performance of your application.</li>
<li><strong>Flexibility in Rendering</strong>: Developers have more control over the rendering process, allowing for optimizations based on user interactions and device capabilities.</li>
</ol>
<h2 id="heading-synchronous-vs-concurrent-rendering">Synchronous vs. Concurrent Rendering</h2>
<p>In traditional synchronous rendering, React processes updates in a single, uninterrupted, blocking UI thread. This can lead to jankiness and unresponsive UI during complex updates. Concurrent Rendering, on the other hand, breaks this pattern by allowing non-urgent updates to be interrupted and resumed, leading to a smoother UI experience.</p>
<h2 id="heading-practical-examples">Practical Examples</h2>
<h3 id="heading-using-suspense-with-concurrent-rendering">Using Suspense with Concurrent Rendering</h3>
<p>React 18 expands the capabilities of Suspense, making it a great tool to use with Concurrent Rendering.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> ProfilePage = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Spinner</span> /&gt;</span>}&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">UserProfile</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">React.Suspense</span>&gt;</span></span>
  );
};
</code></pre>
<p>In this example, Suspense works with Concurrent Rendering to load the <code>UserProfile</code> component. If it’s not ready, the <code>Spinner</code> is shown as a fallback.</p>
<h3 id="heading-prioritizing-updates-with-usetransition">Prioritizing Updates with useTransition</h3>
<p>React 18 introduces a new hook called <code>useTransition</code> that allows developers to prioritize updates. This is useful when you want to ensure that a high-priority update is rendered before a low-priority one.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [isPending, startTransition] = useTransition();
<span class="hljs-keyword">const</span> [mode, setMode] = useState(<span class="hljs-string">'edit'</span>);

<span class="hljs-keyword">const</span> updateProfile = <span class="hljs-function">() =&gt;</span> {
  startTransition(<span class="hljs-function">() =&gt;</span> {
    setMode(<span class="hljs-string">'view'</span>);
  });
};
</code></pre>
<p>In this example, the <code>startTransition</code> is used to mark the profile update as a lower priority, allowing more urgent updates to take precedence.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Concurrent Rendering in React 18 is a game-changer, particularly for complex applications that require a high degree of interactivity. By understanding and leveraging this feature, developers can significantly enhance the performance and user experience of their React applications.</p>
<h2 id="heading-references">References</h2>
<ul>
<li><a target="_blank" href="https://react.dev/reference/react/useTransition#usetransition">useTransition</a></li>
<li><a target="_blank" href="https://react.dev/reference/react/Suspense#suspense">Suspense</a></li>
<li><a target="_blank" href="https://react.dev/blog/2022/03/29/react-v18#what-is-concurrent-react">Concurrent Rendering</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Advanced Hooks in React: Beyond useState and useEffect]]></title><description><![CDATA[Exploring advanced React hooks is key for developers looking to create efficient and scalable applications. This article dives into these hooks, offering insights and practical code examples.
Introduction
React's Hooks API revolutionized functional c...]]></description><link>https://blog.shlomisela.com/advanced-hooks-in-react-beyond-usestate-and-useeffect</link><guid isPermaLink="true">https://blog.shlomisela.com/advanced-hooks-in-react-beyond-usestate-and-useeffect</guid><category><![CDATA[React]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[webdev]]></category><category><![CDATA[hooks]]></category><dc:creator><![CDATA[Shlomi Sela]]></dc:creator><pubDate>Fri, 08 Mar 2024 08:41:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709887193087/af38399a-f9ca-42dc-a842-3674dead0d87.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Exploring advanced React hooks is key for developers looking to create efficient and scalable applications. This article dives into these hooks, offering insights and practical code examples.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>React's Hooks API revolutionized functional components by providing a more intuitive way to handle state and side effects. Beyond the basics, advanced hooks offer nuanced control and optimization capabilities.</p>
<h2 id="heading-usereducer">useReducer</h2>
<p><code>useReducer</code> is ideal for complex state logic, offering a more structured approach than <code>useState</code>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reducer</span>(<span class="hljs-params">state, action</span>) </span>{
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'increment'</span>:
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count + <span class="hljs-number">1</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'decrement'</span>:
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count - <span class="hljs-number">1</span> };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>();
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Counter</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [state, dispatch] = useReducer(reducer, { <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> });
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      Count: {state.count}
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch({ type: 'increment' })}&gt;+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch({ type: 'decrement' })}&gt;-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-usecallback">useCallback</h2>
<p><code>useCallback</code> is critical for preventing unnecessary re-renders, especially with memoized components.</p>
<p><strong>Example and Pitfall:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> MyComponent = React.memo(<span class="hljs-function">(<span class="hljs-params">{ onClick }</span>) =&gt;</span> {
  <span class="hljs-comment">// Component implementation</span>
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ParentComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [value, setValue] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-comment">// Incorrect use of useCallback can lead to unnecessary re-renders</span>
  <span class="hljs-keyword">const</span> handleClick = useCallback(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Value:'</span>, value);
  }, []); <span class="hljs-comment">// Missing dependency: value</span>

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MyComponent</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span> /&gt;</span></span>;
}
</code></pre>
<p>In this example, <code>MyComponent</code> will re-render whenever <code>value</code> changes because <code>handleClick</code> is not correctly memoized due to a missing dependency.</p>
<h2 id="heading-usememo">useMemo</h2>
<p><code>useMemo</code> memoizes expensive calculations to optimize performance.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> memoizedValue = useMemo(<span class="hljs-function">() =&gt;</span> computeExpensiveValue(a, b), [a, b]);
</code></pre>
<h2 id="heading-useref">useRef</h2>
<p><code>useRef</code> is used for persisting values across renders and accessing DOM elements.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> inputEl = useRef(<span class="hljs-literal">null</span>);
<span class="hljs-keyword">const</span> focusInput = <span class="hljs-function">() =&gt;</span> inputEl.current &amp;&amp; inputEl.current.focus();
</code></pre>
<h2 id="heading-usecontext">useContext</h2>
<p><code>useContext</code> simplifies state management across components, making it easier to share data.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> value = useContext(MyContext);

<span class="hljs-comment">// Example of a context provider</span>
<span class="hljs-keyword">const</span> MyContextProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [value, setValue] = useState(initialValue);
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MyContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">value</span>, <span class="hljs-attr">setValue</span> }}&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">MyContext.Provider</span>&gt;</span></span>;
}
</code></pre>
<h2 id="heading-creating-custom-hooks">Creating Custom Hooks</h2>
<p>Custom hooks encapsulate logic and promote reusability.</p>
<p><strong>Example: useFetch Hook:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useFetch</span>(<span class="hljs-params">url</span>) </span>{
  <span class="hljs-keyword">const</span> [data, setData] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">true</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetch(url)
      .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
      .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
        setData(data);
        setLoading(<span class="hljs-literal">false</span>);
      });
  }, [url]);

  <span class="hljs-keyword">return</span> { data, loading };
}
</code></pre>
<p>(You can use any method instead of <code>fetch</code>.)</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Mastering advanced hooks in React is crucial for creating efficient, clean, and maintainable applications.</p>
<h2 id="heading-further-resources">Further Resources</h2>
<ul>
<li><a target="_blank" href="https://react.dev/reference/react">React Official Documentation</a></li>
<li><a target="_blank" href="https://reactpatterns.com/">Advanced React Patterns</a></li>
<li><a target="_blank" href="https://usehooks.com/">Custom Hooks in React</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[React Best Practices for Front-End Developers]]></title><description><![CDATA[React Best Practices for Front-End Developers
React, a vital tool in modern web development demands an organized approach for enhanced readability and maintainability. This guide, inspired by K. Thamodaran's insights and updated with current practice...]]></description><link>https://blog.shlomisela.com/react-best-practices-for-front-end-developers</link><guid isPermaLink="true">https://blog.shlomisela.com/react-best-practices-for-front-end-developers</guid><category><![CDATA[React]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[frontend]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Shlomi Sela]]></dc:creator><pubDate>Thu, 07 Mar 2024 17:45:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709833448678/e9ebe87a-af41-4d17-9127-179012e3ebb9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-react-best-practices-for-front-end-developers">React Best Practices for Front-End Developers</h1>
<p>React, a vital tool in modern web development demands an organized approach for enhanced readability and maintainability. This guide, inspired by K. Thamodaran's insights and updated with current practices, will help you set up your React projects efficiently.</p>
<h2 id="heading-short-introduction">Short Introduction</h2>
<p>Welcome to this guide on React Best Practices, tailored for Intermediate Developers, Advanced Beginners, and Early Career Professionals. If you're familiar with React's basics and looking to enhance your skills, this guide will help you understand key practices for efficient and professional React development. Let's elevate your React expertise together!</p>
<h2 id="heading-1-folder-structure">1. <strong>Folder Structure</strong></h2>
<p>Effective file organization is key. Consider this structure for clarity and ease of maintenance:</p>
<ul>
<li><code>/components</code>: For all React components.<ul>
<li><code>/ui</code>: For UI-specific components like buttons, modals, and inputs.</li>
</ul>
</li>
<li><code>/containers</code>: For components that connect to Redux or any global state.</li>
<li><code>/contexts</code>: For React context files.</li>
<li><code>/hooks</code>: For custom React hooks.</li>
<li><code>/utils</code>: For utility functions and helpers.</li>
<li><code>/assets</code>: For static files like images and styles.</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code>src/
|-- components/
|   |-- ui/
|   |-- [Other Component Folders]
|-- containers/
|-- contexts/
|-- hooks/
|-- utils/
|-- assets/
</code></pre><h2 id="heading-2-component-structure">2. <strong>Component Structure</strong></h2>
<p>Aim for small, focused components. Each should address a specific functionality.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-comment">// SimpleButton.jsx</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> SimpleButton = <span class="hljs-function">(<span class="hljs-params">{ onClick, label }</span>) =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onClick}</span>&gt;</span>{label}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SimpleButton;
</code></pre>
<h2 id="heading-3-state-management">3. <strong>State Management</strong></h2>
<p>Use <code>useState</code> for local state and <code>useContext</code> for more global needs.</p>
<p><strong>Example using useState and useContext:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ThemeContext.js</span>
<span class="hljs-keyword">import</span> React, { createContext, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ThemeContext = createContext();

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ThemeProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">'light'</span>);
  <span class="hljs-keyword">const</span> toggleTheme = <span class="hljs-function">() =&gt;</span> setTheme(theme === <span class="hljs-string">'light'</span> ? <span class="hljs-string">'dark'</span> : <span class="hljs-string">'light'</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">theme</span>, <span class="hljs-attr">toggleTheme</span> }}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeContext.Provider</span>&gt;</span></span>
  );
};

<span class="hljs-comment">// ThemeToggleButton.js</span>
<span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { ThemeContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'./ThemeContext'</span>;

<span class="hljs-keyword">const</span> ThemeToggleButton = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { theme, toggleTheme } = useContext(ThemeContext);
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{toggleTheme}</span>&gt;</span>Switch to {theme === 'light' ? 'dark' : 'light'} mode<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
};
</code></pre>
<h2 id="heading-4-file-naming-conventions">4. <strong>File Naming Conventions</strong></h2>
<p>Consistency is key. Use PascalCase for components and camelCase for utility functions and hooks.</p>
<ul>
<li>Components: <code>MyComponent.jsx</code></li>
<li>Utilities/Hooks: <code>useMyHook.js</code>, <code>formatDate.js</code></li>
</ul>
<h2 id="heading-5-reusable-components">5. <strong>Reusable Components</strong></h2>
<p>Strive for reusability in components to maximize efficiency and consistency across your application.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-comment">// InputField.jsx</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> InputField = <span class="hljs-function">(<span class="hljs-params">{ type, placeholder, value, onChange }</span>) =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">{type}</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">{placeholder}</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{onChange}</span> /&gt;</span></span>
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> InputField;
</code></pre>
<h2 id="heading-6-testing">6. <strong>Testing</strong></h2>
<p>Regularly test components with tools like Jest and React Testing Library for reliability and ease of debugging.</p>
<h2 id="heading-7-performance-optimization">7. <strong>Performance Optimization</strong></h2>
<p>Be mindful of performance. Use React.memo for functional components to prevent unnecessary re-renders.</p>
<h2 id="heading-8-code-splitting">8. <strong>Code Splitting</strong></h2>
<p>Employ code splitting with React.lazy and Suspense to improve load times.</p>
<p>By embracing these practices, your React projects will be more maintainable, scalable, and efficient. Always stay open to new patterns and improvements as React continues to evolve!</p>
]]></content:encoded></item></channel></rss>