{"id":15,"date":"2023-02-10T00:56:26","date_gmt":"2023-02-10T00:56:26","guid":{"rendered":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/?p=15"},"modified":"2023-02-10T00:56:26","modified_gmt":"2023-02-10T00:56:26","slug":"conditional-rendering-in-react","status":"publish","type":"post","link":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/2023\/02\/10\/conditional-rendering-in-react\/","title":{"rendered":"Conditional Rendering in React"},"content":{"rendered":"\n<p>I started this week wanting to do something fairly simple. Like almost anything with CS, I began by thinking &#8220;It can&#8217;t be that hard&#8221;. Three days later, and I finally figured it out.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What Am I Doing?<\/h3>\n\n\n\n<p> I&#8217;m building a React application as part of my capstone project. The React project is build right now so that when a user wants to see something related to their contacts or skills, they do so by navigating between various &#8220;pages&#8221; through a react-router. This is fine for MVP type stuff, but this is capstone, right? Shouldn&#8217;t we have a more polished and professional presentation? I thought so, so my idea was to load this info in a &#8220;feature-pane&#8221; that slides out on the right hand side. <\/p>\n\n\n\n<p>My vision was this: a user has a main homepage that displays an overview of their data. When they want to edit some part of that data, they click on it in the homepage. After clicking, a window would slide out from the right that would contain detailed information about that specific piece of data. The user could edit it in this window and hit &#8220;submit&#8221;, and then the window would slide back and become hidden again.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">My Approach<\/h3>\n\n\n\n<p>The figure below gives you an idea of how our App is structured currently. You&#8217;ll see that we have a top level <code>div<\/code>, under this we have a header, a navigation bar, and then we finally get to our <code>main<\/code> content. The <code>main<\/code> area is where our pages load when different routes are visited. We&#8217;re not actually visiting new pages with these routes, we&#8217;re just replacing what&#8217;s in the DOM with these React functional components. So anyways, my two main questions at this point were &#8211; 1) where do I put the hidden window, and 2) how do I make it so that this window slides out from the right <strong>and<\/strong> overlays the current window (i.e. everything doesn&#8217;t slide around when it pops out)?<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"829\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-1024x829.png\" alt=\"\" class=\"wp-image-16\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-1024x829.png 1024w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-300x243.png 300w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-768x622.png 768w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-1536x1244.png 1536w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image.png 1578w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Starting point of application structure.<\/figcaption><\/figure>\n\n\n\n<p>I&#8217;m going to start with #2. Some quick googling found some tips around CSS animations. Basically, what you do is, on the component that you want to slide in\/out, you create a class name that&#8217;s unique to that component. From there, I defined that class in CSS as having the following properties:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-1.png\" alt=\"\" class=\"wp-image-17\" width=\"230\" height=\"258\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-1.png 414w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-1-268x300.png 268w\" sizes=\"auto, (max-width: 230px) 100vw, 230px\" \/><figcaption class=\"wp-element-caption\">CSS properties of the sliding window.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>The definitions are pretty self explanatory, but the important ones with regard to animation are <code>animation-duration<\/code>, and <code>animation-name<\/code>. The <code>animation-name<\/code> property is then tied to a CSS keyframe, which defines aspects of the animation. There are a lot of in-depth explanations floating around online, but here&#8217;s how I defined my CSS keyframe. Note that the <code>@keyframe<\/code> is followed by the animation-name.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-2.png\" alt=\"\" class=\"wp-image-18\" width=\"177\" height=\"197\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-2.png 328w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-2-270x300.png 270w\" sizes=\"auto, (max-width: 177px) 100vw, 177px\" \/><figcaption class=\"wp-element-caption\">The keyframe that defines the animation over time.<\/figcaption><\/figure>\n<\/div>\n\n\n<p> The phrases <code>from<\/code> and <code>to<\/code> in the keyframe are short for <code>time=0s<\/code> to <code>time=end<\/code>. So basically, at time = 0s, the margin-left of the component with the animation is at 100%. This means that the component will be off screen right. Great, now at time = end, the margin-left will be at 0%, meaning the component will be visible. <\/p>\n\n\n\n<p>I still had to figure out how to get it so that it looked like the window was above the rest of the screen, however. To do this, I started looking into stacked contexts in CSS. To create a stacking context, you need to have positioning of your page elements be something other than <code>static<\/code> (the default). MDN has a great article for understanding the details, but the main thing to take away is that stacking doesn&#8217;t work out of the box. You have to intentionally define positioning for it to work. You can see in the CSS clip above that I chose <code>absolute<\/code>, which means that my component will be positioned at the exact coordinates that I pass it. What are those coordinates in reference to though? Great question, the coordinates that you pass it are <strong>from its closest positioned ancestor<\/strong>. It&#8217;s confusing, I know.<\/p>\n\n\n\n<p>It took me a while to figure out what this meant and the subtle implications that it has. Basically, if you have something like this:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-3.png\" alt=\"\" class=\"wp-image-20\" width=\"350\" height=\"201\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-3.png 659w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-3-300x173.png 300w\" sizes=\"auto, (max-width: 350px) 100vw, 350px\" \/><figcaption class=\"wp-element-caption\">Demo of stacking<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Then when you try to position your &#8220;stacker&#8221;, the position isn&#8217;t going to be from the top left corner of the parent container. Instead, it&#8217;s going to be from the top left corner of the grandparent container. This is because the grandparent is the first ancestor that doesn&#8217;t have a position of <code>static<\/code>. In other words, it was the first ancestor that was deliberately placed on the page. Therefore, the CSS developers decided that this should be your reference point when passing coordinates for positioning. It makes sense once you see it in this light.<\/p>\n\n\n\n<p>Once I understood this, then it was a matter of laying out my components properly so that my sliding container&#8217;s parent was the top level <code>div<\/code>. The top level <code>div<\/code> is the first element to be positioned, so my positioning of the sliding pane would be with respect to the top left corner of the screen. This is the answer to #1!<\/p>\n\n\n\n<p>I still have some more to go on #2 though. Now the question became, how do I toggle this slider? If I were to just slap that class on the slider component, then every time I loaded the App the slider would slide on out. This isn&#8217;t what I wanted. Instead, I wanted it to remain hidden until I clicked something.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Enter Conditional Rendering<\/h3>\n\n\n\n<p>This isn&#8217;t really conditional rendering per-se. Instead, it&#8217;s using state in the component to control the class name that&#8217;s given to a JSX element. What I decided to do was use the <code>useState<\/code> hook in React to store my class name, and give it an initial value of &#8220;hidden&#8221;.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"791\" height=\"53\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-4.png\" alt=\"\" class=\"wp-image-22\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-4.png 791w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-4-300x20.png 300w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-4-768x51.png 768w\" sizes=\"auto, (max-width: 791px) 100vw, 791px\" \/><\/figure>\n\n\n\n<p> I then injected that value of state into my JSX element like so: <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"749\" height=\"155\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-5.png\" alt=\"\" class=\"wp-image-23\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-5.png 749w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-5-300x62.png 300w\" sizes=\"auto, (max-width: 749px) 100vw, 749px\" \/><\/figure>\n\n\n\n<p>Using <code>useState<\/code> means that I can change that class name to whatever I wanted throughout my app by calling the setter function that&#8217;s returned from <code>useState<\/code>. <\/p>\n\n\n\n<p>By doing it this way I can pass the setter function to various components in my app. Then, when I want to change the class name I can simply call the setter and pass a new class name. This will re-render the App and change the class name, which if the class name matches <code>feature-pane<\/code> will trigger the animation. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>That was a wild ride, and it took a lot of trial and error to figure out exactly how to get it done. Here&#8217;s what the final code looks like, you&#8217;ll notice that I put the feature-pane right underneath the top most <code>div<\/code>, so that my positioning is correct:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"908\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-6-1024x908.png\" alt=\"\" class=\"wp-image-24\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-6-1024x908.png 1024w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-6-300x266.png 300w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-6-768x681.png 768w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-6-1536x1361.png 1536w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/6463\/files\/2023\/02\/image-6.png 1574w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">The final result after adding the sliding feature.<\/figcaption><\/figure>\n\n\n\n<p>There&#8217;s still one more gotcha that I didn&#8217;t explain that has to do with how you set your display in CSS on the initial class. You have to use <code>hidden<\/code> or else you&#8217;ll encounter a strange flash of a component that then disappears right before starting to slide out from the left. I&#8217;ll leave it to you to figure out why this is occurring because I think we learn the best by troubleshooting issues. It&#8217;s a pretty easy issue to figure out once you understand the mechanics. In any case, I hope that you enjoyed learning this with me.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I started this week wanting to do something fairly simple. Like almost anything with CS, I began by thinking &#8220;It can&#8217;t be that hard&#8221;. Three days later, and I finally figured it out. What Am I Doing? I&#8217;m building a React application as part of my capstone project. The React project is build right now &hellip; <a href=\"https:\/\/blogs.oregonstate.edu\/philpeiffer\/2023\/02\/10\/conditional-rendering-in-react\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Conditional Rendering in React<\/span><\/a><\/p>\n","protected":false},"author":13144,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-15","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/wp-json\/wp\/v2\/posts\/15","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/wp-json\/wp\/v2\/users\/13144"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/wp-json\/wp\/v2\/comments?post=15"}],"version-history":[{"count":3,"href":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/wp-json\/wp\/v2\/posts\/15\/revisions"}],"predecessor-version":[{"id":25,"href":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/wp-json\/wp\/v2\/posts\/15\/revisions\/25"}],"wp:attachment":[{"href":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/wp-json\/wp\/v2\/media?parent=15"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/wp-json\/wp\/v2\/categories?post=15"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/philpeiffer\/wp-json\/wp\/v2\/tags?post=15"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}