Overcoming Challenges and Expanding Horizons: GSoC Adventure

Hey folks,
This is the third blog in the series where I document my journey through the Google Summer of Code program. In this blog, I will be sharing what I have learned and accomplished during weeks 3 and 4. If you're interested in reading about my progress from the first and second weeks, you can find them here.

The issue with GitHub pages

At this stage, the user interface (UI) was nearly ready for publication. However, a major issue arose that needed to be addressed. Our plan was to host the application on GitHub Pages, but we discovered that React Router's BrowserRouter is not compatible with GitHub Pages. The problem stems from BrowserRouter's use of the browser's history API to store and manage the URL of the current page. Unfortunately, GitHub Pages does not support this API, rendering BrowserRouter unusable.

After conducting some research, I stumbled upon a discussion on Stack Overflow that provided a solution. The alternative we found was to use HashRouter instead, which is supported by GitHub Pages because it does not rely on the History APIs. It's worth noting, though, that using HashRouter is not recommended for SEO purposes as it is not as search engine friendly as BrowserRouter.

Then, switched to using createHashRouter instead of HashRouter since new routers were introduced in React Router version 6.4. These new routers provide support for data APIs, allowing us to enhance performance. During this process, I learned about the loader function, which proved to be quite helpful in directly providing data to React components. Here's an example:

const fetchData = async () => {
  const response = await fetch("https://example.com/data");
  console.log(response);
  return response;
};

const router = createHashRouter([
  {
    path: "/",
    Component: MainContainer,

    children: [
      {
        index: true,
        Component: ReportDataHandler,
        loader: async () => fetchData(),
      }
    ],
  },
]);

const root = createRoot(document.getElementById("root"));
root.render(
  <RouterProvider router={router} />
);

In this code snippet, I first defined the routes and mounted the components accordingly. Then, I defined a function called fetchData responsible for fetching the necessary data and returning the response. This data is then provided to the component using the loader function. It's important to note that the component will not be rendered until the loader function is resolved and the data is available.

importance of async/await

One other important thing I learned is about the async/await keywords, which play a crucial role in function execution. Although JavaScript is a single-threaded language, meaning that only one line of code can be executed at a time, it provides asynchronous features that allow code to run in the background while other code continues execution. This asynchronous behavior is particularly useful when performing tasks that need to run in the background while simultaneously executing the next set of code. However, controlling this asynchronous behavior is sometimes necessary to avoid errors, and that's where the async/await keywords come into play.

Let's consider an example using the fetchData() function mentioned earlier. This function is asynchronous and returns a promise. By using the await keyword, we can wait for the promise to be fulfilled before executing the console.log() function.

The async/await keywords bring several benefits. They make asynchronous code more concise and readable, improving the overall code quality. Additionally, they can help enhance the performance of your application by preventing the main thread from being blocked, ensuring smoother execution and responsiveness.

Context APIs in React-router

I also learned about and implemented the Context API in React, which allowed me to make data centrally available in my application. React's Context API provides a way to share data between components without the need to manually pass props down at every level. This can be particularly useful for sharing common data such as themes, locales, or user authentication information.

Let's explore a simple example to better understand how it works:

const ThemeContext = createContext({
  theme: "light",
});

const ThemeProvider = ({ children }) => {
  return (
    <ThemeContext.Provider value={theme}>
      {children}
    </ThemeContext.Provider>
  );
};

const App = () => {
  return (
    <ThemeProvider>
      <MyComponent />
    </ThemeProvider>
  );
};

const MyComponent = () => {
  const theme = useContext(ThemeContext);
  return (
    <div>
      The current theme is {theme}.
    </div>
  );
};

In this example, we define the ThemeContext context object to share the theme variable between the App component and the MyComponent component. The ThemeProvider component wraps the App component and sets the theme variable to "light". Within the MyComponent component, we use the useContext() hook to access the theme variable and render it to the screen.

By utilizing the Context API, we can easily provide and consume data across multiple components in a more efficient and organized manner.

Adding new feature

After that, I started working on adding another important feature. When testing the implementation with the Bowtie Tool, it produces result data that needed to be visualized in an intuitive way within our frontend application. Therefore, I focused on adding a new feature that allows users to upload their locally generated data for visualization of their implementation's performance.

Additionally, I incorporated a loading animation to enhance the user experience of the front-end application. After receiving feedback and undergoing reviews from both my mentor and community members, the changes I made were successfully merged into the main branch. (PR links - #241, #297)

Summary: The learning experiences during this period have been enriching, and I'm grateful for the progress made so far. I look forward to sharing more details about my progress in the near future, so stay connected. Thank you for reading this blog until the very end. Peace!