Fixing husky/lint-staged command not found error

I ran into this annoying error while switching from WebStorm to Visual Studio Code. After I prepared my first commit on VS code, I received the following error message:

“.husky/pre-commit: line 4: lint-staged: command not found
husky – pre-commit hook exited with code 127 (error)
husky – command not found in PATH=/Library/Developer/CommandLineTools/ blah blah”

Solution

I use husky version 8.0.1 and this is how my pre-commit file looked like:

As most error messages do, this one also refers to the correct location to fix the issue. I changed the line 4 as below:

npm run lint && npx lint-staged && npm run stylelint

It worked like charm. I hope this suggestion works on your case too 🙂 The same error can occur because of several reasons. I am aware that my suggestion may not solve the issue for all. However, here is some more insight about my problem.

I noticed that running “lint-staged” command did not work when I ran it at Mac’s regular terminal. It did not work at Visual Studio code terminal, either. But it somehow worked fine in WebStorm’s terminal. I still don’t know why. WebStorm might be adding npx to package commands before running it? Or it is added to some other custom path. This does not matter much.

npx is node package runner, so expecting “lint-staged” to work on its own is not possible at VS code terminal. I remembered this fact while I was checking the github documentation of lint-staged 🙂

Sercan Leylek / OSLO

Advertisement

New approach to same key problem in React

Every React developer must have received following warning on their browser console: “Warning: Each child in a list should have a unique “key” prop.”. Well, most of us know the answer to this problem. React JS uses virtual dom algorithm and it expects you to assign a unique key value to your list items. Let’s assume that you have an array of people and you are rendering those people one by one as div or li items. There are plenty of articles that offer the solution for an ideal world. However, I will introduce you a new approach which solved the case in my real world.

Before we dive into the problem, let’s have a quick summary of some of the best practices out there.

  • Every list item should have a unique key.
  • Key value should not be changed between renders.
  • Do not use index value (such as incremental array loop value) as React key.
  • Do not use random value as React key (such as some alphanumeric value produced by nanoid).

All of these sounds fair. If you fail at one of these points listed above, your application behaviour will be unpredictable. If you settle with these advices, your application may certainly work fine, but in my case, it simply did not. Because business realities are not like how things work in best practices’ book. There are priorities, costs and many other boundaries while trying to solve a front-end problem.

Definition of problem

Below is a component which helps the user register as many people as s/he wishes. The user should input first name, last name, and social security number attributes of the subject person. After the user fills in the info about first person, clicks ‘add person’ button and so on. The user also has delete option. Please watch the following gif animation.

Vertical design demo

As you must have noticed, there are severe problems in this component and all of them are related to same React key issue.

  • onBlur event on each text-input causes a loading animation. Why?
    • To block the user from typing too fast. Otherwise, I had more serious data related problems.
  • Webpage scrolls to some random position some times. Why?
    • Since there are duplicate items with the same React key, the browser does not know where to render.
  • Dynamic validation and keyboard navigation are almost impossible. Why?
    • Because again browser does not know where to show the error message or where you were after each render.

This is a nightmare.

Our backend systems send us the same key value for each tuple. Think it this way: There are 3 values for each person in same tuple (first name, last name and social security number). For example, every first name input box has the same key value in Person 1, Person 2, … Person n. We have to solve this problem without making any changes in backend data. This is the true origin of all the problems above.

Solution

In an ideal world, you should make the backend to send your front-end application unique keys for every data tuple, right? But assume that our backend is not able to solve it because of its other dependencies with other internal systems. Life is not perfect.

Therefore, I tried the forbidden best practices hopelessly to cure the issues. First of all, you cannot use loop index value attached to your key values because when you delete one person, the next persons get shifted backwards and all you get is a more confused state. Secondly, when you use random values as React keys (via nanoid), then your application is changing key values after each render and the browser gets confused. Apparently, this is a dead end. So, what to do?

Advice #1: Rethink your design

The component in gif animation above uses vertical design. In other words, every data tuple is rendered and as the user adds more items (persons), the list is growing. If we replace vertical design with horizontal one, every component would have a unique React key. As long as you render one unique id per component, every thing should work fine, shouldn’t it? Watch the next gif carefully if it is working or not.

Horizontal design demo

Nope! It is not working, but why not?

We have two persons in our list:

  • Person 1: John Bravo
  • Person2: Sara Brown

The user clicks the navigation buttons. The header and button elements are incrementing from Person 1 to Person 2, but the values in text boxes are still the same. The reason is violation of unique React keys. You might be rendering unique key one at a time, but the keys of Person 2 are the same as Person 1. Therefore, the virtual dom assumes that the values in these text boxes are not changed at all and it does not re-render because of its reconciliation algorithm.

“When comparing two React DOM elements of the same type, React looks at the attributes of both, keeps the same underlying DOM node, and only updates the changed attributes.” (Reference: React Docs)

Rethinking design is not an ultimate solution for this case, but it will still help.

Advice #2: Bypass Reconciliation Algorithm

If you learn the rules well enough, you can break them in your own favour. My next advice is a pure hack, but it will be a solution. I actually got the inspiration from database studies. Do you remember the terms ‘primary key‘ and ‘foreign key‘ from DMBS?

A primary key is “which attributes identify a record,” and in simple cases constitute a single attribute: a unique ID. (Ref: Wikipedia)

A foreign key is a set of attributes in a table that refers to the primary key of another table. The foreign key links these two tables. (Ref: Wikipedia)

The definition of primary key is very similar to React keys and foreign key is what we are going to create here.

I want to have a control on when the component will render or not. So, I should have a mechanism which will inform React’s reconciliation algorithm it is correct time to render the DOM.

Firstly, create a hook which will count the renders, but not all renders. This hook will keep the renders that I approve.

const [renderCount, setRenderCount] = useState<number>(0);

Second, create a useEffect(…) hook with dependencies that I choose.

useEffect(() => {
  setRenderCount(renderCount + 1);
}, [index, deleteItemTriggered]);

Here is our foreign key. The cooperation of index and deleteItemTriggered hooks. index is changed whenever the user switches from Person 1 to Person 2 (Navigation button click). deleteItemTriggered hook is self-explaining. Whenever the user clicks on delete Person button, this boolean hook is fired. The combination of these two events create my new unique key, primary key.

Lastly, I use renderCount value in addition to the component ID which is duplicate throughout different persons.

<div key={`${element.id}_${renderCount}`}>
   {RenderTextInput(element, ... blah blah)}
</div>

Here is the result:

Everything works fine 🙂

No more random scrolls. No more loading animations. Everything works as it should.

To solve this problem, I googled so many posts and web pages. There was no what-if scenario. What if I am supposed to solve my problem without unique keys given to me via my backend? I could not find an answer to this problem. So, these two advices explain above helped me solve the problem for good. This might be an inspiration for those who got stuck in real world just like I did.

If you have a better solution suggestion, please drop a comment.

Sercan Leylek / OSLO

Free Artificial Intelligence Course

As a front-end developer, I happen to hear these terms quite often: Deep learning, machine learning, neuroscience, … However, I did not have any knowledge nor considerable experience in these fields. Also, when you don’t know something, it scares you even more, because fear leads to the dark side.

Many developers have the fear of replacement in the future. We fear that artificial intelligence may suddenly cast us out. This is certainly because of the ignorant and lazy man inside of us all. Therefore, I decided to thinner this grumpy man’s voice in me and followed the artificial intelligence course created by University of Helsinki and reaktor.com.

Course Content

Elements of AI will introduce you common AI patterns, terminology, problem solving techniques and many other theoretical topics that you should cover. Their curriculum is well organised and comprehensive. All in all, this beginner course helps you build fundamental knowledge to start your AI development career. On the other hand, the creators of the course aimed to target a broad range of individuals. Therefore, it is not specifically tailored for programmers or other IT roles. So, you don’t have to have programming skills. However, if you are already an IT professional, this is a big plus to comprehend the discussions.

Here is a list of my favourite topics throughout the course:

  • How to define AI?
  • AI for board games like tic-tac-toe, go, chess.
  • Why we should use different methods to solve different problems?
  • How can we reach for General AI?
  • AI Winter
  • The Bayes Rule
  • The types of machine learning
  • Neural networks

Exercise Tips

You will be asked to complete some exercises on almost every section. Most of them are tests that can be answered with some radio buttons. However, I recommend you to be careful while answering the questions. Not all of them are easy to answer and there are some tricky questions. So, think twice before pressing the submit button. I got 85% success rate, but it would be higher if I were more careful and patient before making my mind about the answers.

The course also provides some open-ended questions. Elements of AI created a smart solution to review the answers. They use the other students’ judgment to score one another. For example, after you write your answer (several paragraphs) for an open-ended questions, you are required to review 3 other students’ answers for the same question. So that, the community builds a fair and reliable control mechanism for itself.

After the course completion, you will receive a free digital certificate approved by University of Helsinki. Of course, the certificate is just a make up. What you have learnt and what you will do with gained knowledge is way more significant than a piece of paper. However, this certificate might have academic value for university students. Elements of AI grants you 2 ECTS credits. According to the info on their website, these credits are only valid in Finland, but you may try to convince your faculty in another EU country. Just try.

What’s next?

I have been informed by Elements of AI, thanks to the continuous growth environment of Fremtind AS. My colleague Berit Klundseter dropped an introductory post about this course via Fremtind’s social network. Then, I talked to our Senior Machine Learning Engineer Emanuele Lapponi and he recommended another course where I could program some practical cases. So, my AI journey continues with the support of my colleagues.

I hope this post made you curious about AI topic and if you also have dedication to finish the course, may the force be with you! 🙂

Sercan Leylek

How to mock addEventListener in React Testing Library?

This question puzzled my mind for some time and I noticed that there is no good post which provides an up-to-date answer to the challenge. Basically, this article will help you solve your testing problem in React and I also provide you a sample project with a working application.

Description of the problem

You have a component which adds some event listener inside useEffect() block. You wrote some unit test, but quickly realised that your unit test runs the code inside useEffect, but it does not run the function that your event listener is adding. So, you should basically mock addEventListener to solve it, but how?

Sample Project: offline-modal

offline-modal is a simple application which utilizes online/offline events. (See reference here: developer.mozilla.org)

When you turn off internet on your machine (or by using the throttle functionality on Chrome), the application shows some information to the user. After the connection is asynchronously restored, the user receives the feedback about connected internet for 3 seconds. And this message also finally disappears.

Offline Modal Demo

Implementation of offline-modal > OfflineModal.tsx

Before we jump into the unit testing discussion, it is wise to review the implementation.

const OfflineModal: React.FC = () => {
    const [connStatus, setConnStatus] = useState<number>(ConnectionStatus.Online);
    const connStatusRef = useRef(connStatus);
    connStatusRef.current = connStatus;
    useEffect(() => {
        const toggleOffline = () => {
            setConnStatus(ConnectionStatus.Offline);
        };
        let timer: NodeJS.Timeout | undefined;
        const toggleOnline = () => {
            setConnStatus(ConnectionStatus.SwitchingOnline);
            timer = setTimeout(() => {
                if (connStatusRef.current !== ConnectionStatus.Offline) {
                    setConnStatus(ConnectionStatus.Online);
                }
            }, 3000);
        };

        window.addEventListener('online', toggleOnline);
        window.addEventListener('offline', toggleOffline);
        return () => {
            window.removeEventListener('online', toggleOnline);
            window.removeEventListener('offline', toggleOffline);
            if (timer) {
                clearTimeout(timer);
            }
        };
    }, []);

I will explain the critical lines here.

Line 2: This our state management which keeps track of current connectivity status.

Line 19 and 20: I basically add event listeners to follow connection status here. Two separate functions are assigned to online and offline cases.

Line 22 and 23: Before the component (OfflineModal) is unmounted, we remove the event listeners.

In the latter part of the component, I render 3 different connection status (Offline, SwitchingOnline, Online) in a Switch statement to inform the user. That’s basically it.

Unit Test Implementation > OfflineModal.test.tsx

This is the critical part. I wrote the function below to mock internet connection in Jest environment.

const mockInternetConnection = (status: string) => {
    const events = {};
    jest.spyOn(window, 'addEventListener').mockImplementation((event, handle, options?) => {
        // @ts-ignore
        events[event] = handle;
    });
    const goOffline = new window.Event(status);
    act(() => {
        window.dispatchEvent(goOffline);
    });
};

Line 1: I created a parameter called status. In this example, example input could be ‘online’ or ‘offline’ string values. These are actually the event names to be added.

Line 2: An empty json object is created.

Line 3: The core of mocking happens in this scope. We spy on window.addEventListener call. Whenever subject code runs this function in due implementation, we will add the corresponding event type into its events array. So that, we will be able to run requested event in our unit test. This event can be any other event such as click, keydown, etc.

Line 7: This line creates a fake event. But it does nothing on its own. I only assigns the fake event object into a const called goOffline.

Line 9: Here we trigger our fake event just like the implementation code does in reality.

After creating the function (mockInternetConnection), writing the unit test suite is much simpler.

describe('OfflineModalComponent', () => {
    it('switches offline and back online', () => {
        render(<OfflineModal />);
        mockInternetConnection('offline');
        expect(screen.getByText('You are offline')).toBeInTheDocument();
        mockInternetConnection('online');
        expect(screen.getByText('It worked! You are back online! :)')).toBeInTheDocument();
    });
});

This unit test turns off the user’s internet connection and verifies the correct output. Later on, it switches the connection back online and runs one more check.

I hope this blog post helps you solve a similar problem on your side 🙂 Good luck!

Here is the link to the GitHub repository: https://github.com/SercanSercan/storksnest/tree/master/offline-modal

Sercan Leylek

6 Advice on Mixpanel Integration

User analytics is one of the most fundamental features that every popular web application should perform. Without collecting data about user activities, one can never be sure of the user experience. The developer team will invest days on some functionality, but unless they know how many users use this precious feature, they will only guess and hope that the users are benefiting from it.

In other words, “Without data you’re just another person with an opinion.”, W. Edwards Deming.

To clarify the ambiguity, my production team (http://meldeskade.no) decided to use popular business analytics tool, Mixpanel. Our single page web application is built with ReactJS, uses Jøkul Design System and hundreds of users visit the website to report their insurance activities every day. In short, meldskade.no is a typical SPA which promises the user to follow a set of operations under some sections and completes the user request somewhere along the way.

From the perspective of a front-end developer, I thought including Mixpanel tracking would be a simple task. However, as our team gained more and more experience in the field, I started to realize the obstacles. We followed the path of ‘learning by doing’ and eventually, our Mixpanel tracking started to deliver us data. So, this article will help to those who are in the beginning of their Mixpanel journey and looking for some useful advice.

#1 Don’t underestimate the integration work

Know your enemy first! Adding Mixpanel to your web application is an integration process and system integration is maybe the most problematic fields in Information Technology. Because linking different systems increases the complexity. Although the relationship between a web application and Mixpanel is a one-way road, the integration will still be painful, and it has the potential to produce unforeseen errors.

For instance, if you perform some tracking event before initializing the Mixpanel with the code below, the application will have a fatal error and whole website will be down for the user. This error can seem obvious, but one exceptional case for some users might be the end of the show. Therefore, do not underestimate the complexity of integration process.

import { MixpanelUtils } from './MixpanelUtils';
...
MixpanelUtils.Init();

#2 Document every tracking operation first, code later

Teamwork is required in order to integrate a web application with Mixpanel. Naturally, a web developer cannot sit alone and write all the tracking operations on his/her own for a large system. Product owner, architect, tester, and tech lead should give their consent on what user activities will be tracked besides developers. Since people from different roles are involved in the process, it is important to keep decisions in one open document.

The team of meldskade.no created a table which lists all tracking events. We included many columns for every event such as definition, trigger case for the tracking, its parameters, development status and we even wrote down the JIRA ticket for each tracking. This strategy helped the team solve the complexity of the problem.

Besides, we still keep this document active. Whenever the team needs to implement a new Mixpanel tracking, we start the work by documenting. So, document first, code later.

#3 Don’t try to track too many events on first deployment

Since our team underestimated the complexity of adding Mixpanel to our website, we set an ambitious goal for our delivery. We tried to implement at least 10 different tracking operations in one go. However, you should also implement configuration code for Mixpanel. These are OptInTracking, alias, identify, getting cookie consent of the user, etc. This is the threshold that one team should initially come over to reach for tracking events. When a team wraps all of these in a single deployment, the development work grows much more than expected. Therefore, the goal on first deployment should be a successful configuration of Mixpanel and a couple of meaningful tracking operations.

#4 Surprise! Surprise! You need a backend developer 😀

This is a point that our team failed to foresee. We basically thought we had all the data out there. We should only write some well-organized tracking operations in JS and everything will go smoothly. However, the data flow of a web application is not like what you see on a webpage as a human being. For example, you want to track some category data after the user clicks a section, but the component that you are triggering the event from may not contain the category information as a prop. Therefore, you need to ask the backend developer to provide this additional data via corresponding API call.

This tip is very much related to the advice #2. If the developers communicate about where and how to obtain the data attributes in the documentation, the process will go simultaneous and smooth.

#5 You will discover defects along the way

This might be one of the greatest paybacks for all the effort performed to reach the goal. As you implement more tracking on different components of a React application, you will discover some defects that have been omitted by you and other fellow front-end developers. React redundant rendering problems are known, but mostly ignored defects. And they are not easily discovered by tester, neither they truly create some run time error, but they are there. While adding more tracking operations, you will clearly see those mistakes and you will have the opportunity to fix them with some refactoring process. This practice will increase the performance of the application.

#6 GDPR is everyone’s responsibility. Speak up when in doubt.

Every team member should be observant on potential GDPR violation. More data does not help to understand user interaction better, but key data does. Users’ private data does not play any role while measuring the efficiency of an application. Therefore, speak up when you are in doubt of some data that your team is about to collect.

Sercan Leylek

Finishing Master’s Degree in Seven Years

I admit the fact that the title of this article sounds like a movie name. In other words, I did not travel as much as Brad Pitt did in Seven Years in Tibet, but my master’s degree has also been a challenging academical adventure.

Most people reach their master’s degree between 2 to 3 years. They start their master studies right after the undergraduate programme, and they follow master courses besides some part-time work. However, I did not have this luxury. After completing my bachelor studies in Turkey, I had to get a full-time job in IT (2009). After I established my financial freedom in a couple of years, I decided to follow master’s degree in IT at University of Oslo (2014).

5 years of work experience helped me realize the value of master studies. In 2009, I was not quite aware of its significance, but I came to the conclusion that completing some master’s degree is a good career and personal development investment.

In 2014, I talked to my manager at Thomson Reuters and we reduced my working hours by 40%. I was supposed to pass three courses in the first semester, so I worked at my professional job 3 days a week. However, I managed to pass only two courses because it was not possible to follow all theoretical and lab lectures of three courses with only 2 workdays free in a week. Meanwhile, my monthly income naturally cut by 40% and this quickly ended up having minor financial problems for myself.

In the spring semester of 2015, I worked 4 days a week and aimed to pass only one course. This tactic paid better since I managed to create some balance between financial independence and academical growth. However, it was certainly not enough. Because I was supposed to get 60 credits in my first year, but I had managed to get only 30 credits.

In fall 2016, I picked some completely wrong course for myself and got away from master’s degree. I had also consumed my energy and focus. And at the end of first two years, the University of Oslo kicked me out of master’s programme since I did not manage to finish it on time.

After this period, I enrolled at master studies once more, but my request was denied. (2017) The university aims to give the chance of study to almost everyone, but if you failed once, you are not welcome as you applied for the first time. I applied once more, and rejected once more. (2018) This time, I sent an e-mail to the university and asked about why I had been rejected. And they said I was rejected because of my lack of academical growth. This is actually polite way of saying this: “You only got 30 credits in 2 years. If you somehow manage to gain more credits, we may consider to accept you back”.

I decided to change my strategy after this news and learned about “Admission to Single Course Studies”. It roughly works this way:

  • The university places every student at some course.
  • Every semester, some courses lack students.
  • They open admission for outsiders (like me) for these courses.
  • You are allowed to pick one among 2 or 4 courses.
  • If you manage to pass your selected course, you get 10 credits.

Good deal! Following this path, I applied a course almost every semester and started to collect 10 credits once in a while. I was not able to pass a course every semester because I did not have any suitable course for me at some semesters, but I managed to collect 30 more credits within two more years. As a sum, I had 60 credits. In other words, I managed to become a more attractive student for the board which decides who would be accepted to the master’s programme. And this plan worked.

In fall 2020, I have been officially re-accepted as a master student at University of Oslo. To be able to graduate, you need to have 120 credits in total and my lacking 60 credits were locked behind a successful master thesis wall. At that time, I have been lucky to meet my current employer Fremtind AS. They had been implementing something called “design system”. It was completely new to me at that time. As I learned more about design systems, I started to see the connection with platforms. I had learnt about platforms at one of my single courses and managed to tie these two worlds for my master thesis. This process helped me write my thesis about some topic which I actually work in a daily basis. Finally, I delivered my thesis in December 2021 and finished my master’s degree.

Pros and cons of my path

Taking master courses besides professional work is definitely not easy. You have to dedicate your evenings and weekends to reading research papers, preparing homework and passing final exams. This is lots of stress, but it is a great opportunity to discover one’s true potential. I apparently enjoyed reading many research papers. You have to read lots of things, but these valuable articles contain surprising secrets. When you experience such aha moment, it builds up your character and you start seeing patterns from multiple perspectives.

Moreover, academic studies are mostly about theory, but I was at a practical world at the same time. I was able to apply some new knowledge that I gained at a lecture immediately at my working hours. I realized this advantage already in the first weeks of my path. You learn some new thing at school, you get to the work and apply it instantly. This is luxury in professional life.

As you see, I had to take a painful path for my master’s degree, but I have been stubborn enough to get it done. I honestly don’t know how many times I thought I would quit and sometimes I even quit this dream, but reconsidered the situation and applied a new remedy to get over the obstacles.

Instead of struggling with master’s degree, I could have invested in a startup idea, some framework or anything else, but that was what I wanted for myself. I did not want to die without knowing what was academical life all about and I definitely think that it was worth it.

I hope this story inspires more people out there struggling with similar challenges. You may stop believing in yourself, take a rest if you fall down, but just for a while. Then, keep moving towards your goal.

Sercan Leylek / OSLO

Calculating Distance in Google Maps with React and Typescript

After a long pause, I am back to my Google Maps application. In other words, the 3rd video of the series is out! In this video, our Google Maps application turns out to be something useful. The application lets the user calculate distance between some points on the map. Below is the list of tasks completed in part 3:

  • Create home address marker with center and zoom functionality (panTo and setZoom)
  • Calculate distance between home address marker and custom markers (computeDistanceBetween)
  • Draw a line between home and selected marker (polyline)

Github URL: https://github.com/SercanSercan/youtubeStuff/tree/master/google-maps

This article will point out some of the critical code snippets in the video. I prefer to make up some questions that you may ask along the way.

1. How to create markers with PNG files?

You don’t have to use SVG content to create markers in Google Maps. In some cases, you may prefer to use PNG instead. For example, while creating the home marker of my application, I used a PNG file. Place the image into some folder that is located under your public folder (such as public/assets/images/…) and the icon attribute of your google.maps.Marker constructor receives the url parameter as shown below.

const homeMarkerConst:GoogleMarker = new google.maps.Marker({
    position: location,
    map: map,
    icon: {
        url: window.location.origin + '/assets/images/homeAddressMarker.png'
    }
});

2. How to create an event for a marker in Google Maps?

You can implement some operations on markers via adding event listeners on them. Preferably, you should add your event listener and the corresponding function right after you create the marker. The code snippet below shows the event listener that I added to my home marker. The arrow function changes the center point of the map with the location of home marker.

homeMarkerConst.addListener('click', () => {
    map?.panTo(location);
    map?.setZoom(12);
});

The gif animation below shows how this listener performs in the application. After the user clicks on home marker, the map centers and sets the zoom level to 12.

Homework! 👀

As you see, my zoom operation in the code snippet above is not actually smooth. Clone my repository and create a function called smoothZoom. This function should zoom gradually. I want you to change the zoom level in every 100 milliseconds. (💁 Hint: smoothZoom should be recursive)

3. How to compute distance between two markers in Google Maps?

We so far learnt how to perform some function when a marker is clicked, right? So, if I should calculate the distance when a marker is clicked, what am I supposed to do? The answer is adding another click event listener. Before that, you should add another library to your Api URL. If you’d like to calculate distance in Google Maps, you should use the function computeDistanceBetween(…, …). This function lies under geometry library of Google Maps library. Therefore, your Api URL should be something like this:

maps.googleapis.com/maps/api/js?key=${your_key}&libraries=geometry,places&language=no...

After making sure that libraries have geometry, now I can add the click event listener which gets the position of two markers and computes the distance between them.

marker.addListener('click', () => {
    const homePos = homeMarker?.getPosition();
    const markerPos = marker.getPosition();
    if (homePos && markerPos) {
        const distanceInMeters = google.maps.geometry.spherical.computeDistanceBetween(homePos, markerPos);
        console.log(distanceInMeters);
    }
});

After adding polyline code and few more other things, the code above helped me measure the distance between home marker and custom markers as the gif below shows:

4. How to use React Hooks inside marker event listener?

This is the most challenging part while implementing Google Maps with React. The event listeners are part of vanilla javascript and they have no respect against the render mechanism of React. They only remember the hook values of the moment that you added the listener. Therefore, when you try to perform some setter operation of a hook, its value will not always be updated. I mean the hook value will actually be updated, but your listener functions may still remember the former value of the hook. (I know! This part is a bit complex. So, read this paragraph again and ponder)

To fix this, you should remove your listener function and add it again. So that, your new listener event will keep the updated version of your hook value. Therefore, I keep the listener ids of my events in a hook array and whenever I am supposed to update some hook value inside the event listener, I remove all previous listeners and add them again. I won’t share a code snippet for this part, so you’d better watch the last 20 minutes of the video 😁

Hopefully this blog post will help someone in the future! And again hopefully I will make the 4th video some time soon.

Sercan Leylek

TypeError: Class constructor HTMLElement cannot be invoked without ‘new’

This error message has been a headache for me this week. I noticed that there were no good posts to cover it in the internet, so I decided to write this post. Hopefully, it will help someone in the future.

Technology stack

  • React
  • Typescript
  • testing-library/react
  • Jest

Definition of the problem

This error occurs while running a unit test. The component that you are running has probably some 3rd party code which contains class components and your EcmaScript configuration in tsconfig.json is not able to compile this file. Therefore, your test fails at some random point in the 3rd party code.

Solution

Unfortunately, there is no single solution for this error because every environment has its own problem because of similar situation. I will show how I handled it while I was using NRK’s core library.

1) Install custom elements es5 adapter for your project.

npm i custom-elements-es5-adapter

2) Import custom elements adapter to your setupTests file

import '@webcomponents/webcomponentsjs/custom-elements-es5-adapter';

3) Run your test again. It should work 🙂

Sercan Leylek

Highlights of Beyond Design Sytems Meetup

Insurance company Fremtind organised a design system meetup on November 4th. The name of the event is Beyond Design Systems. The text below summarises the purpose of the gathering:

“The digital product industry has been welcoming design systems for a while. Many organizations have been better able to preserve brand guidelines, speed up time-to-market, or improve the user’s experience by establishing and maintaining a functioning design system.

This event will attempt to look beyond: To uncover the good, the bad, and the ugly experiences from inside our design systems. What has thrilled users? Where has it gone wrong? How did we prevail – if at all?”

Because of Corona measures, the event was broadcasted online via company’s youtube channel. The experts who are located in different parts of the globe have been available via a YouTube URL. That was quite comforting. If you are eager to learn about design systems, you can watch the whole session below:

Meetup – Beyond Design System – Fremtind – November 2020

what is a design system?

There are several definitions out there, but I will describe it with my words: A design system is a collection of design rules, patterns and reusable elements which help a web application develop faster and in a correct way.

For example, almost every web application requires a loading animation, footer, date box, etc… Most of these elements are common in every project and they all require time to build, consistent style, accessibility, validation, standard UX, UI guidelines and more. So, the design system assists your project to cover those needs at reusable parts of the final outcome. Therefore, digital product industry has been recently moving towards design systems.

Highlights

“Design systems should be built on collective culture, not individual achievement.”

Above is a quote from Glenn Brownlee who is the leader of design system, Jøkul. The inclusion of people are needed to make a design system work. If people do not participate, then there would be no progress. Brownlee basically underlines that a design system is actually a living thing. It evolves and the people need to understand why the system is necessary. As the process matures, actors of design system will not follow the rules just because they are told to do so, but they will see these rules as an expected way of doing. In other words, the rules will become their new normal. 

Brownlee also added: “If all you have is a component library, you don’t have a design system. However, once people become part of the movement, that means you have a design system.”

A similar thought was also mentioned by another participant of the meetup, Mike Hall (UX Lead for the Service NSW Transactional Design System). Hall said that if a system was not updated and maintained, it would die very quickly.

I should confess that my favourite presentator of the meetup has been Eirik Fatland (Lead Designer at Fremtind). He mostly shared some of his interesting experiences while expressing his thoughts about design systems. That was truly engaging.

“In Fremtind, we for example have weekly design critique sessions that are important while establishing culture. In design critique session, anyone can bring any design they are working on and they receive feedback on it. Sometimes feedback leads to discussions. The discussions involve everyone in the room and they become wiser.” ~Eirik Fatland

And finally, Morgane Peng had a stunning presentation. She is the director of UX at Societe Generale. I think the Dunning-Kruger effect was a perfect example while she was explaining their design system journey.

The DunningKruger effect is a bias in thinking, usually where a person is unaware of how badly they grasp a subject, not understanding that they are failing at it. Peng says that she and her co-worker thought they built some useful tool in the beginning and afterwards they started to receive feedback and complaints from the users of their design system. Therefore, they fell to the valley of despair because of their mistakes. This experience helped them understand that building design systems is not easy. After putting more work and engagement with additional actors, they started to understand what they were actually building and before they reach to the plateau of sustainability, more partners joined them. As a result, Peng says that a design system is 20% craft and 80% people.

All in all, I hope there would be more interesting meetups soon. And if you are curious about design systems, I recommend you to take a look at this blog post: Everything you need to know about design systems.

Sercan Leylek

Creating Markers on Google Maps with React + Typescript

This is the part two of my Google Maps series. I don’t truly know where we are heading with this app, but I will keep teaching you the secrets of Google Maps programming with React and Typescript. Few days ago, I released the last video. This article serves as a cheatsheet of what I implemented on Youtube.

Creating Markers on Google Maps with React + Typescript (Part 2)

Link to GitHub Respository 

IMarker Interface and marker hook

First, we should create an interface for our marker, right? I want to keep three basic data attributes for a marker. Of course, the label of a marker could be also added here as another string value, but I want to keep things simple. Maybe we do it in the next video.

Based on this interface, I also create the marker hook which will store the content.

const [marker, setMarker] = useState<IMarker>();

Event Listener

While working with Google Maps on React, you should still write some Vanilla JS code as well. I don’t like this, but that’s the way it is. As soon as the map hook is initialised, we add a click listener into this function. This event listener will return us a latLng event object which will be used to get the coordinates from geocoder.

coordinateToAddress

As you notice, I invoke a function called coordinateToAddress() whenever the user clicks somewhere on the map. The click event of google.maps namespace returns us a typical event (e), but this e event has a special attribute called latLng. This is our location value. In this function, I pull three different data types from geocoder. I get the address, latitute and longitude. Just what I need to update with my marker hook.

At this point of the program, our Map component successfully retrieves the coordinates of clicked point and it stores the data in our hook (marker), but we do not illustrate any marker to the user, yet.

addSingleMarker

I created this function just for convention. If we decide to create an array of IMarker objects (which means storing several markers on the map at the same time), we would create another function called addMultipleMarkers. But let’s see what addSingleMarker() does first. It simply follows the changes on marker hook with a useEffect and whenever it is updated we invoke addMarker function.

addMarker

So, here is a much more reusable function. This is actually the place where our Map component will create the marker and it will show it to the user.

google.maps.Marker receives a JSON object where the options are almost limitless. There are so many attributes that you can use to customise your marker, but I only used fundamental parts here (position, map and icon). I also created a dummy function called getIconAttributes() which is only used for the output of icon. You may refer to Google Maps manual for further customisation.

Task

The gif animation below shows how I create markers on the map, but there is a problem. As I click a point on the map, the component successfully creates a marker. However, when I create once more, the previous marker is still there although the marker hook changed its value. So, try to create a function which will remove the previous function. Good luck!

I hope you enjoyed this post. I will keep on writing more about Google Maps. Take care!

Sercan Leylek / OSLO