<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mateusz Kwiecień</title>
    <description>The latest articles on DEV Community by Mateusz Kwiecień (@mkwiecien).</description>
    <link>https://dev.to/mkwiecien</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2596111%2F34f0396b-84f2-447a-90b1-1f104cd06886.png</url>
      <title>DEV Community: Mateusz Kwiecień</title>
      <link>https://dev.to/mkwiecien</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mkwiecien"/>
    <language>en</language>
    <item>
      <title>Readundant states</title>
      <dc:creator>Mateusz Kwiecień</dc:creator>
      <pubDate>Wed, 25 Dec 2024 08:57:26 +0000</pubDate>
      <link>https://dev.to/mkwiecien/readundant-states-3kea</link>
      <guid>https://dev.to/mkwiecien/readundant-states-3kea</guid>
      <description>&lt;p&gt;Working on multiple React projects, the most common issue I encounter is unnecessary states. &lt;/p&gt;

&lt;p&gt;Such 'bad' states have a negative impact primarily on the quality of the code as well as its maintenance and development. They can also adversely affect the performance of the application or cause surprising bugs that are difficult to diagnose.&lt;/p&gt;

&lt;p&gt;In this post, I will try to show an example of redundant state and discuss the potential problems it causes, as well as how to quickly and safely refactor it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;The example will be based on a real case. I will try to maintain a relatively original but simplified code structure. Surely, in many places, it would require significantly more refactoring. I do this intentionally because in real projects, there isn't always the possibility to spend days or weeks refactoring the entire code. Sometimes, we have to settle for just quick wins.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function useUserLoader() {
  const { data: users } = useQuery({
    queryKey: ["userList"],
    queryFn: () =&amp;gt; getUserList(),
    placeholderData: [],
  });

  return { users };
}

function useUsersOptionLoader() {
  const [userOptions, setUserOptions] = useState([]);
  const { users } = useUserLoader();


  useEffect(() =&amp;gt; {
    if (users) {
      setUserOptions(users.map(mapUserToOption));
    }
  }, [users]);

  return userOptions;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case on the start we will have &lt;strong&gt;4&lt;/strong&gt; renders. In case you don't believe me, as proof, I'm adding a screenshot from the profiler.&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%2F70softt22t5flpb4a38b.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%2F70softt22t5flpb4a38b.png" alt="Screenshot from React Dev Tools showing the fourth renders that occurs" width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's go step by step and see what is happening in each render.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First render&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In this step, &lt;code&gt;useUserLoader&lt;/code&gt; starts fetching data from the server and returns an empty list, which is defined in the &lt;code&gt;placeholderData&lt;/code&gt; prop. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useUsersOptionLoader&lt;/code&gt; initializes the &lt;code&gt;userOptions&lt;/code&gt; state with an empty list.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useEffect&lt;/code&gt; hook is called, and that hook updates the userOptions state with a new value, which is an empty array.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useUsersOptionLoader&lt;/code&gt; returns the current state of &lt;code&gt;userOptions&lt;/code&gt;, which is an empty array&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Second render:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;This render occurs because &lt;code&gt;userOptions&lt;/code&gt; state changed.&lt;/li&gt;
&lt;li&gt;In this step, &lt;code&gt;useUserLoader&lt;/code&gt; is still fetching data from the server and returns an empty list.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;useEffect&lt;/code&gt; hook is not called because the &lt;code&gt;users&lt;/code&gt; value didn't change.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useUsersOptionLoader&lt;/code&gt; returns the current state of &lt;code&gt;userOptions&lt;/code&gt;, which is still an empty array.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Third render&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In this step, &lt;code&gt;useUserLoader&lt;/code&gt; finishes fetching data from the server and returns the populated user list.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;userOptions&lt;/code&gt; state is still an empty list.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useEffect&lt;/code&gt; hook is called, and it updates the userOptions state with a new value, which is a mapped array of users.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useUsersOptionLoader&lt;/code&gt; returns the current state of &lt;code&gt;userOptions&lt;/code&gt;, which is still an empty array.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Fourth render&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In this step, &lt;code&gt;useUserLoader&lt;/code&gt; returns the user list that was fetched in the previous render.&lt;/li&gt;
&lt;li&gt;The userOptions state is a mapped array of users, which was set in the previous render.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;useEffect&lt;/code&gt; hook is not called because the users value didn't change.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useUsersOptionLoader&lt;/code&gt; returns the current state of userOptions, which is a mapped array of users.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Key Takeaways:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Three renders return an empty array (first, second, and third), with the userOptions state getting updated only in the third render after the useEffect hook is called.&lt;/li&gt;
&lt;li&gt;The fourth render reflects the updated userOptions state, which is now populated with the mapped array of users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These 4 renders could potentially be a problem in large apps that render a lot of data. However, in most cases, this won't be a big deal.&lt;/p&gt;

&lt;p&gt;The next issue with this code is that you need to spend additional time understanding what happens inside the useUsersOptionLoader. The combination of useEffect and useState introduces extra complexity. While this is a relatively simple hook, in more complex cases, you might encounter hooks with many lines of code, multiple states, and numerous dependencies. In such situations, you could easily spend hours analyzing and trying to understand the logic—and after making changes, you may end up breaking other parts of the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;The solution to this kind of code is quite simple: remove the useEffect and useState, and just return the mapped value directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function useUsersOptionLoader() {
  const { users } = useUserLoader();
  return users.map(mapUserToOption);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case on the start we will have &lt;strong&gt;2&lt;/strong&gt; renders. In case you don't believe me, as proof, I'm adding a screenshot from the profiler.&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%2Fxemy3qqdpfc2cufvzbgg.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%2Fxemy3qqdpfc2cufvzbgg.png" alt="Screenshot from React Dev Tools showing the two renders that occurs" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's go step by step and see what happens in each render:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First render:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;useUserLoader&lt;/code&gt; starts fetching data from the server and returns an empty list, as defined in the placeholderData prop.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useUsersOptionLoader&lt;/code&gt; returns an empty array.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Second render:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;useUserLoader&lt;/code&gt; finishes fetching data from the server and returns the populated user list.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useUsersOptionLoader&lt;/code&gt; returns the mapped array of users.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Instead of the four renders you had previously, now there are only two, which are directly tied to fetching the data in &lt;code&gt;useUserLoader&lt;/code&gt;. Additionally, the code is more concise with no extra &lt;code&gt;useEffect&lt;/code&gt; or &lt;code&gt;useState&lt;/code&gt; hooks. The &lt;code&gt;useUsersOptionLoader&lt;/code&gt; code is now much clearer and more straightforward, making it easier to understand what’s happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sumarize
&lt;/h2&gt;

&lt;p&gt;With simple improvements in the code, it’s possible to optimize the application’s performance, reduce the code, and make it more readable. In the next article, I will show another example of redundant states and a simple solution to improve your app.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
