Fetch Data for Storybook Components With Container Pattern

Using a container pattern to deal with complex components.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Storybook for React Apps course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Storybook for React Apps, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Storybook for React Apps
  • [00:00 - 00:20] In this lesson, we're going to be talking about data fetching and how to deal with components that do data fetching in Storybook. In the previous lesson, the restaurant section component was added to Storybook, and it was a pretty simple process because the component doesn't take a lot of props. It's just a stateful component that does everything by its own. However, if you switch stories, you'll see that it takes some time to switch from the loading state to the success state.

    [00:21 - 00:52] So if we open the dev tools and we go to the network panel and also filter by fetch requests, if you switch stories again, you will notice that there's a request happening to the actual back end. And then this is really not reliable because, you know, the components in Story book, they should always respond correctly every single time you access them. And in this case, as you can see, it's taking a long time for the server to respond, and maybe it can respond with an error. And that's really not what we expect. And one of the biggest advantages of Storybook is that it should work offline so that you can work in the train or in the plane or whatever, right?

    [00:53 - 01:23] So let's do something about it and still make that possible. Let's see what's going on with the restaurant section component. It's a stateful component that does pretty much everything. So it starts by fetching the data from the back end and then rendering a loading state while added. And then once the backend returns the data, it will process that data and depending on what comes, it will render a successful or maybe an error state. And as you can see, there's a lot of responsibility happening in the same component and it because it's self contained, once you move it to Storybook, it will do the same thing, right?

    [01:24 - 03:34] So it will always try to fetch real data from the backend into Storybook. One way of fixing this situation is by using a container pattern, which is a well-known React pattern for dealing with situations like this. So coming back to our scenario, the component was doing a lot by itself. And we could separate the responsibility into two different components, one which is the container component. And that's the one which will deal with the business logic and data fetching. And all of the data will just be passed down as props to a new presentation or component that will render differently based on the props. And this allows us to detach the data fetching to the actual rendering logic. And then we can just move the rendering component to Storybook. And that will make things so much simpler. And coming back to our code, we see that in the restaurant section stories, we are using the component which is coming from this file. And in this file, we have a single stateful component that does the data fetching and everything necessary to render the loading state and the success state. And all of these things are happening at once. But in here, I created a container file for you, which essentially separates the components into two different components. The first one is a presentation or component that just receives the inputs and outputs the events. And then the second one is the container component that takes care of the logic and passes information down to presentation or components. So the restaurant section container, it will be having all of the business logic. And the data will be passed down just as props to this one. So if we see over here, a lot of the information is just being used to render normal states. And that makes things so much simpler. The added benefit is also that if the restaurant section presentation or component were to do a lot of calculations, because now this is a peer component, it can actually be memorized and you get performance benefits. So let's go back to the stories. And let's instead of using the restaurant section component, let's use the presentation or component from the container file. So this is called restaurant section components. And let's alias it to restaurants section, because we don't want to deal with the renaming of the imports. And now that we're using a presentation or component, that also means that we have to pass down the restaurants as props. And the restaurant data comes from this stub folder, we have a restaurant file, which contains pretty much all the marks that we need. So let's import it from there.

    [03:35 - 03:57] So we import from four levels above stub restaurants, and it's called restaurants. When we go back to storybook, we see that the component is rendering correctly. And if we switch stories, it 's instantly rendering. The added benefit is that now, because this is fully presentational, we have access to every single prop, which is being sent, we can actually take care with the data and see how the component renders.

    [03:58 - 04:58] We could maybe change one specific property of one element and see how it renders over there. And we can actually toggle the raw mode here and copy this JSON, which is based on the changes that we just made. And then we can update our stubs. And also because the presentation or component is just emitting events. So if we click on this component, which is supposed to say on restaurant, click in the action span, we also get that with the idea of the restaurant that we're clicking. So we can make sure that the function behaves correctly. And also the is loading is a prop that we can easily set. That means that we can create a new story for the loading state. So let's just go ahead and do that. And the loading state doesn't need restaurants because well, it's loading. So we just need to pass the loading flag to true. And once we go back to storybook, we will see that there's a new story over here with the loading state. So now it's much simpler to see all the rendering states of your component. And another benefit of the container pattern is that if you were to write tests for these components, they will be much simpler because now the rendering and the logic are separated. And this is pretty much it. So is there any downside to this approach?

    [04:59 - 05:30] Yes, of course, depending on your code base, it could be that a few or maybe no components follow this container pattern, which will mean that a lot of refactoring is needed to achieve this approach. Another downside is that depending on how complex your components are and how up in the tree you want, let's say you want to render a page using this pattern, you need to do a lot of prop drilling in order to make this work. And prop drilling has its shortcomings. So it's really up to you to decide whether or not this is for you. But you know, leave the decisions to the end of this module because we're going to discuss other approaches to I'll see you in the next one.