5

Let Objects Communicate With React | by Philipp Rembold | Apr, 2022 | Bits and P...

 2 years ago
source link: https://blog.bitsrc.io/let-objects-communicate-with-react-e3dc49b4944d
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Let Objects Communicate With React

An Object-Oriented React App Design Part 2

This is part 2 of my mini-series regarding an object-oriented approach to react apps. If you missed it, read part 1 here.

In this article, we want to explore how we can solve the following problems:

  • have multiple representations of an object displayed in an app
  • update the screen representation of an object when it changes its state and
  • let the message flow between objects follow user interaction with the app

The idea for the app we’re taking as an example was created when my girlfriend and I were trying to decide what we wanted to eat the next evening and also plan for the week. We knew we were having our favorites, but we couldn’t think of them off-hand. And so we decided to make a list. And instead of making that list — and our plans for a week— on paper, I decided to take the opportunity to finally learn how to create apps using react.js

The app is rather simplistic and hosted on GitHub pages, and unfortunately, it’s in German.

You drag and drop meals from the recipe book on the right-hand side to the meal plan on the left-hand side and in the end, you export the plan as a picture.

Feel free to play around with it and also, dig into the code if you want to. You’ll find it here. (And, please, don’t judge me for the misspelling of the hobbit’s name. I was young when I chose that handle for myself…)

Now, without further ado, let’s have a look at the first problem we want to solve.

How to Have Multiple Representations of an Object Displayed in an App

We have an object (a meal). The object implementation itself is not very interesting, and the interface at the moment just knows how to do two things, and one of those is how to export itself for various formats. These various formats allow us to change how the meal is represented on the screen independently from all the other formats and the meal class itself.

Disclaimer: the code as presented here is purposefully incomplete. The complete code can be found in the repository. Copy and paste from the following listings will produce syntax errors, though.

The mealNameFormat, for example, is a projection of the name of the meal, e.g. ‘Pizza Tonno’. Exporting is done, at the moment, by spreading the object and the formatters take the properties they want — this is mostly due to my laziness.

However, note that I can change the export functionality later. The contract between Meal and Format is defined by the (implicit) type I’m currently exposing, and there is no going back from it, but I can safely extend it and completely change the way the properties are calculated.

This is the builder pattern in reverse, I can deconstruct an object without putting all that knowledge in the object itself.

Each formatter needs to implement a render function that returns a react.js component.

We could change the interface to also allow other forms of rendering, e.g. returning complete HTML files, but for the moment at least, we want to stick to react. Note, however, that even if we were to go there, there would be no need to change existing formatters.

We’ll have a look at the other formats in the next part of the series. For now, let’s look at state:

How to Update the Screen Representation of an Object When it Changes its State and Let the Message Flow Between Objects Follow User Interaction With the App

Granted, this is a lengthy description, but in an app, the state of an object changes due to user interaction. To explore this further, we want to look at the drag and drop functionality. If you check the user stories in the repository, you’ll find the following:

The Canteen Chef sits down and plans the dishes for a week. They search in their recipe book for dishes they want to cook that week […] They write down their decision on a plan and hang it on the kitchen wall[…]

The app you see (when this article is published) solves this problem. These are the pertinent parts of the code and we’ll discuss them at length.

First, there is a class module ‘chef’ which exports a class ‘chef’. The chef is a singleton, powered by ES6 modules. The chef can pick a dish (misnamed ‘meal’ — this is cause for refactoring!) and add that picked dish to the meal plan.

This class represents the user of the app, or rather, the user in the role of chef. Then, there is the recipe book — this is the container for all the dishes. Since there is only one representation of that recipe book on the screen, it doesn’t make use of the formatter pattern as the meal does but renders itself (not shown here) and delegates the rendering of the dishes to the meal object in the ‘list item format’.

These components are surrounded by a draggable ‘box’ — picking up that box means that the user has picked it, and thus the chef is told to ‘pick that meal’.

The bulk of the code is the meal plan itself. First, we need to look at the custom hook ‘useSubscriber’ and the generic observer pattern implemented here, though.

The hook is a preconfigured useEffect-Hook which makes it easy to register an observer to a publisher. The defaultPublisher is a container for subscribe, unsubscribe and publish functions.

The complete module is introduced solely to avoid unnecessary code duplication. Let’s have a look at how it is used.

The MealPlan class acts as a publisher (and thus implements the interface). Instead of implementing the pattern, we copy the default implementation over to the class.

The meal plan can add a meal for a day (and currently replaces the current meal, allowing us to remove meals by adding an empty one), and this is the only state-changing operation. It needs to inform the observers by calling ‘publish’.

On rendering, the whole instance of the meal plan is passed to the component, instead of only the properties needed for rendering. In a statically typed language, the component would probably be defined as MealPlanComponent({publisher, mealPlanProperties})and it would be called like this <MealPlanComponent publisher={this} mealPlanProperties={...this}/>.

However, we can dispense with this kind of nitpicking and resolve that dual role in the component itself — but let’s keep this in mind, as it might come in useful.

The first few lines of the component are where the magic happens. We define the state (by spreading the mealPlan object) and register an observer (basically setState) on the mealPlan object.

This now means that the state of the component is updated whenever the mealPlan object calls ‘publish’.

Last but not least, let’s look at the ‘MealPlanDayComponent’. If the meal passed to the component is the empty meal, it will accept a drop and tell the chef to go ahead and put the meal into the meal plan for the day represented by the component.

This then results in the call of ‘publish’ and a state change for the MealPlanComponent and, consequential, a state change of the MealPlanDayComponent.

Incidentally, when writing this article, I found the code a little bit lacking in elegance. There will be refactoring and I encourage you to have a look at the code in the repository.

Conclusion and main takeaways

In this article, we have looked at how we can have multiple representations of an object on the screen and how, by the introduction of formatters, we can change, add or remove representations without touching the class itself.

We have further explored how we can update the representations when the state of an object changes by use of the useState hook and a custom useSubscriber hook which allows us to easily register the component as an observer for the object and update the state of the component when the state of the object changes.

Please let me know your thoughts in the comments and stay tuned for the next part of the series where we’ll look into user input changing state and why a formatter might be a publisher.

Build composable web applications

Don’t build web monoliths. Use Bit to create and compose decoupled software components — in your favorite frameworks like React or Node. Build scalable and modular applications with a powerful and enjoyable dev experience.

Bring your team to Bit Cloud to host and collaborate on components together, and speed up, scale, and standardize development as a team. Try composable frontends with a Design System or Micro Frontends, or explore the composable backend with serverside components.

Give it a try →

https://cdn-images-1.medium.com/max/800/1*ctBUj-lpq4PZpMcEF-qB7w.gif

Learn More


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK