How 40 Lines of Code Improved Our React App’s Performance by 70%
14
February
2022
Engineering

How 40 Lines of Code Improved Our React App’s Performance by 70%

How 40 Lines of Code Improved Our React App’s Performance by 70%
Vishnupriya Bhandaram
0
 minutes ↗
#
engineering
#
engineering diaries
#
web-development
#
reactjs
#
analytics
Engineering

On Appsmith, developers can quickly build any custom business software with pre-built UI widgets that connect to any data source. These widgets can be controlled with JavaScript. We created this framework to help developers save on valuable time building complex applications for internal uses within their organizations. For this to work for everyone, we believe that the core parts of Appsmith need to run smoothly and should be continuously improved.  Appsmith’s UI is built using React, Redux, Web Workers, Immer among other things. 


In this blog, Sathish Gandham, a frontend engineer focusing on UI performance at Appsmith, will talk about how we improved the editing experience on Appsmith.

What is the Editing Experience on Appsmith? 

The editing experience on Appsmith involves writing bits of code to customize the functionality of the widgets and writing special commands and actions into the application. It is a crucial function in the Appsmith framework. 

Lag and Delay 

Building an application on Appsmith involves dragging and dropping widgets onto the canvas and writing custom code on the editor; however, we noticed that while editing text/code in the canvas, the editor would often freeze, resulting in a less than optimal user experience. When building an application, there should be no delay or lag. This was a huge issue that needed our immediate attention from an engineering perspective. For a natural typing experience, users want the keypress latency to be under 100ms, though 50ms would be ideal. 

To solve this problem, we needed to understand what happens when a user types. For this, we used: 

React profiler: This measures how often components in the application render and the “cost” of rendering. The profiler helps in identifying parts of an application that are slow. In our case, this allowed us to understand what components were rendered as we typed. 

Chrome Performance tools: This helped us quantify the problem, measure our progress, find the code taking longer to execute, and find unnecessary repaints. 

Please note that the React profiler is part of the React Developer tools browser add-on which is available for Chrome and Firefox.

From the React profiler, we see three pairs of long commits; each of these corresponds to the following property pane, and UI widget renders. Ideally, the property pane should render much faster than the canvas since there is nothing changing in the property pane except the input we are editing. Even the canvas should be rendering the widgets currently in use and not the rest. We realized that this was not the case and needed to be fixed. 

We profiled the property pane issue in isolation to identify what it takes to render it. For this, we used the performance tab in Chrome DevTools to see what happens when the property pane opens. This gives us some helpful information. 

  • ComponentDidMount of code editor is taking a lot of time 
  • Styles are also taking a long time to render
If you see the property pane commit in the screenshot above, you will notice that evaluatedValuePopup also takes significant time.


Here’s how we listed the tasks that lay ahead of us: 

  1. Identify as to why all the widgets were rendering when they don’t have to and fix it
  2. Optimize the code editor [Not apparent from the React profiles]
  3. Identify why all the controls in the property pane are rendering and fix it
  4. Optimize the global styles
  5. Optimize the evaluatedvalue pop-up

In this blog, I will talk about how we went about the first task. Before I get to that, here are a few tips for profiling: 

  • Try to split your problem into smaller pieces and profile them. With this, you won’t crowd your profile, and you can find the performance issues with ease. 

Example 1: To improve the editing experience, we just profiled a single keypress. 

Example 2: To profile a drag and drop action, we can split that into drag start, move, and drop.

  • Leave the application idle for 5 seconds after starting the profile and before stopping it. It will make it very easy to identify the work that has been done. [See A & C From profile above]
  • To measure the overall performance improvements, instead of measuring each optimization individually, it’s better to consider focussing on the overall scripting and time taken to render during an action. You can get this number from the chrome performance tab. [B & D from profile above]
  • In the React profiler, don’t just focus on the large commits. Go through each commit at least once, and see what’s getting rendered in that commit. The chances are that one or two small components are accounting for all those renders.

Here’s a short guide on reading the React profile: 

  • A: List of commits during our profile
  • B: The commit we are looking at
  • C: Details about the selected component (WidgetsEditor). Our widgets editor rendered three times during the profile at 6.1s, 8.6s, and 14.1s. 102ms, 328ms,83.1ms is the duration each commit took; it is not the total time the selected component took to render.
  • D: Zoomed in view on the component we selected and its children.

Here are the notes on the profile based on which we worked on improving the editing experience. You can download the attached profile and import it in your React profiler to follow along or just refer to the image above.

Please note that the React profiler is available only when you open a react app in dev mode in Chrome/Firefox, if you don’t have a local React development set up, you can use the standalone React developer tools to read the profile. 

Here are instructions on how to install it and start it: 

Install

# Yarn

yarn global add react-devtools

# NPM

npm install -g react-devtools

Run

react-devtools

Follow this link to read the detailed notes from the profile we did to improve the editing experience on Appsmith. 

I’ve put some notes here for your reference: 

1. Evaluated value opening. Not related to editing.

2. Widgets editor, not sure why.

3. Editor focused. We should be able to avoid the rest of the property pane from rendering.

4. Small changes to property pane, its header, lightning menu, and action creator. Nothing changes for them, so they should not be re-rendering. Memoization can help here.

5. Same as above. 

6. We get the evaluated value back. Entire widgets editor is re-rendered (Deduced this from one of the two updates to table), we can optimise this

- If each widget subscribes to its data independently, we should be able to avoid the unnecessary renders of the widgets by

- Doing a deep check at the widget level

- update the store with only values that changed. 

7. PropertyPane is rendered with the updated value. EvaluatedValue taking most of the time.

8. From 8 to 17, these are commits like 4 & 5 above. 

9. 18 & 19 are widgets editor and property pane. I don’t see why these are required. I will look into it. 



Widgets Render When Not Needed


One of the most loved features of Appsmith is reactive updates. With reactive updates, you can see the widget change and show data. With traditional programming, you would have to reload the page in order to see the update in the widget. This is achieved by updating the data tree as and when you change something on the canvas and using the updated data tree to re-render the app. Due to the amount of data we have and the number of calculations we need to do, it took a long time and blocked the main thread.

To solve this problem, we moved the evaluations to a web worker freeing the main thread. A brilliant move to solve the problem at hand, but this created a new issue. The problem here was due to object reference changing. Since the data tree is coming from the worker, we would always get a new reference for every item in the tree even though only some of them changed. This reference change was making all the widgets re-render unnecessarily.


A few approaches we tried to solve this problem were:

  1. Get what keys changed from the worker (worker has this information) and update only those values in the reducer. This did not work because the list of keys was not complete. 
  2. Compute the diffs between the current data tree and the one received from the worker and update only what changed. Though this prevented the renders, we did not improve the overall scripting time we measured earlier. The reason is, computing the diffs itself took a lot of time, which would happen twice for each change.


Web Worker to the Rescue 


We moved the task of computing the diffs to the worker and used the deep-diff library to compute the diffs and let immer take care of immutability.

This helped us in two ways:

  1. Offloaded the expensive task of computing the diffs on the main thread.
  2. Reduced the size of the data we transfer between worker and the main thread (this was never a bottleneck for us, though).


This change alone brought down the keypress latency by half.


Instead of replacing the entire data tree from the worker, we get the only changes (updates) and apply them to the current state. applyChanges is a utility method from deep-diff. Immer takes care of the immutability.


If there’s anything to be said about performance improvement, it’s this, don’t take performance for granted and profile your code on a regular basis. Even a few lines of change or configuration can lead to a great performance gain. 



I hope you found this blog helpful. If you’d like to get in touch with Satish, ping him on Discord or visit his website.

Appsmith Roundup: Powerful Widget Grouping Options, Undo-Redo, and New Widgets
6
October
2021
Monthly Round-up

Appsmith Roundup: Powerful Widget Grouping Options, Undo-Redo, and New Widgets

Appsmith Roundup: Powerful Widget Grouping Options, Undo-Redo, and New Widgets
Vihar Kurama
0
 minutes ↗
#
community
#
engineering
#
open-source
#
applications
Monthly Round-up

We’re back again this month with updates from the last 30 days. We like to work hard! We’ve shipped many features, fixed bugs, and launched Hacktoberfest with a series of fun events. You can check them out here.

Powerful Widget Options

From grouping widgets to copy-pasting them to undoing or redoing them on the canvas, we’ve got everything covered for you to customize your applications on Appsmith. This makes your app-building experience much more accessible, smoother, and of course, fun!

To use the widget grouping feature, you have to select all required widgets on the canvas with your pointer. This will create a widget group highlighted in a rectangular dotted box; next, you can drag the rectangular box anywhere across the canvas to move them all in one go. Additionally, widget groups can also be duplicated and copied, or deleted. You can find all these options on the top-right corner of widget groups.

There’s no such thing as error-free creation; it’s common to make mistakes while building apps. Often,  we accidentally delete widgets while building the UI and have to redo everything. With the new undo-redo feature, you can make changes in the canvas using simple keyboard shortcuts. 

Undo - Command / Control + Z

Reo - Command / Control + Shift + Z

We also resolved some critical issues for copy-pasting widgets. Now, the widget won’t overlap, and all the functionalities such as deleting them, customizing them would be working as expected!

New Widgets and Customisation Options

We got four more new widgets last month! A stat box widget to display all the metrics on your dashboards, a checkbox widget to configure multiple checkbox inputs, a beautiful audio recorder widget to record audio on your applications, and finally, a tree select widget for selecting options in a nested tree-like structure. Cool right? Here are the quick previews of these new widgets.  

Additionally, we’ve upgraded all the widgets styling options to give developers more control over customization. Now, you can add background color, shadows, borders, border radius to almost all the widgets where there is a chance of customization. Of course, we’ve tried them. We have a new product designer who joined us recently who had built this beautiful dashboard on Appsmith.

Don’t forget to chat with us on our discord channel if you want to see more such internal tools and designs!

Configuring Page

We’ve added a new option to configure all your pages in the application in one place. Using this, you can rename, reorder, duplicate, and delete pages within few simple clicks. To access it, click on the application name and select the page option from the dropdown to configure pages under the application. Below is a screenshot that shows how easy it is to manage your application pages on Appsmith!

Introducing JS Snippets!

JavaScript is like fuel at Appsmith. We can use JS anywhere across the application, from binding data to writing functions to implement complex JS transformations using the moustache bindings. But not everyone is a JS expert; even we sometimes google to get stuff done. Hence to make it handier we’ve introduced a super cool feature, the JS Snippets. Some common use-cases can help you with fundamental transformations, functions, binding, and many more. 

Here’s how you can access this:

  1. Open the Quick search and navigation on the top menu bar.
  2. Select use snippets
  3. Search for Snippets

Before you use them, you can also test them out with your connected data. 


We’ve got a host of other bug fixes and updates too, be sure to check out our release notes here

See you next month with more updates! Do follow us on Twitter, Youtube, and Linkedin to stay up to date.  

Hacktoberfest 2021: Let the Contributions Begin!
27
September
2021
Announcement

Hacktoberfest 2021: Let the Contributions Begin!

Hacktoberfest 2021: Let the Contributions Begin!
Vishnupriya Bhandaram
0
 minutes ↗
#
hacktoberfest
#
announcement
#
developer
#
engineering
Announcement

Time indeed does fly because it feels just like yesterday when we hosted our first ever Hacktoberfest last year! And what a year it has been.

We started Appsmith because we wanted to create a developer-first product to make an engineer’s life easy. From being a small, little-known project on Github, we now have 5K stars. This wouldn’t have been possible without our community; apart from giving us incredible feedback, they also contributed immensely to our codebase, from contributing new integrations to helping solve bugs. We now have over 100 contributors, and we want to expand our community (that means you!), empowering them to contribute to a project that will always remain developer first.

And so, we’re back again this year for an exciting month-long virtual festival supporting open-source projects. We love it because it’s celebratory and community-oriented! At Appsmith, we genuinely believe open-source can take the way we build things to new heights. And our commitment to the community will never waver.

In that spirit, we are kicking off the Hacktoberfest 2021. In the run-up to the actual code-fest, there are going to be many talks! We will be bringing together folks from other awesome projects to talk about Hacktoberfest and Open Source. Be sure to check these out. You will definitely get to learn more about how to get involved in open-source projects. And yes! We’re ready to swag it out, too, for every valid PR! And contributors who submit more than 4 PRs and invite others to contribute to our repository will get a special prize. You are welcome to contribute to the issues on Appsmith’s repository on Github. Be sure to check contribution guidelines, review, and merge policies. Please note that not all pull requests will count towards Hacktoberfest 2021.

Contributing to open-source projects is an excellent way for users to become contributors. And it’s both a fun and rewarding experience. Sure, it can be scary to begin, and many think that only code that implements significant features matters. Well, I am here to tell you that it’s not true. We believe that no contribution is too small. Bug fixes, documentation updates, submitting articles are all fantastic ways of participating.

Hacktoberfest is open to all: Students, developers, anyone really. Background no bar. To this end, this year, we’ve included several newbie-friendly issues in the challenge to give a warm welcome to first-timers.

If you’ve still got some doubts about participating or need some queries answered, head over to our Hacktoberfest channel on Discord, and we will be happy to help you out!  To know more about how you can participate in this event, take a look at our Contributor Guidelines and Code of Conduct.

Happy Hacking! 🐱‍💻

Engineering=Growth
14
April
2021
Engineering

Engineering=Growth

Engineering=Growth
Akshay Rangasai
0
 minutes ↗
#
product
#
engineering
#
open-source
#
internet
Engineering

Product led growth as a concept is making the rounds. Investors cannot get enough of it, Twitter is filled with threads about this topic, and many dedicated channels and podcasts are talking about this “new” growth paradigm. However, product-led growth is not something new and has existed for ages. The internet and digital products (Tech companies - Primarily SaaS and consumer internet) have brought this in focus. Growth in organizations has always been tied to marketing and sales, but product-led growth forces us to change that perspective and think about organizations differently.

In this post, we will explore the history of growth for companies, the rise of product-led growth, and why the key to driving it is to think about engineering and product teams as revenue generators rather than just cost resources that need to be allocated optimally.

How the internet changed growth for companies

Historically, the three key pillars to driving growth are Price, Product, and Distribution. Price and product dictate demand, while distribution ensures products are available to satisfy demand. The new world with digital products changes a little bit but with massive consequences. Nevertheless, to understand why we need to focus on product as the key driver of growth, we need to dive into the history of product development and how businesses monetized products.

Before the advent of computers, most of the real-world products were physical objects that needed to be manufactured, priced and distributed. Product development took ages, manufacturing took as much time, and as if this was not enough, you needed to find distributors to distribute products. Computers solved this problem by making each step easier and faster and created a whole new category of digital products.

The software was quicker to make and did not have the manufacturing overheads, but distribution was still a problem. The other big problem in both models was the product itself. You did not know if the product was good or not till you bought it. The ability to have information to make sound product decisions was again constrained by distributing a publication (Like Gartner). If you subscribed, you got it; if not, you didn’t. This meant that product development was a cost, and sales and marketing were revenue-generating functions. Distribution was key. Most companies treated engineering and product as allocated resources, and sales took a lot of the value generated from selling this product. This was just how the old world worked.

The software also hacked the working capital cycles that plague most manufacturing companies. Not only do you need to set up the infrastructure and pay wages to workers, but you also had to foot the bill for each item being made, and then you made it back when selling the product. As your company scaled, so did the requirement of capital. Scaling rapidly was not just a function of people but also a function of how much money you had, or how many loans you could get to foot this bill. Software hacked this cycle; it was infinitely distributable, without any additional cost of production. If you had enough distribution, you could scale easily. The collection cycles also made the companies cash-rich and did not need as much money as other product companies to grow.

Then came the internet. While you can claim that the internet made distribution cheaper, it isn’t really clear if it did. It made distribution faster, but discovery (of products and customers) was still an unsolved problem. Gartner subscriptions came via email and mail. Search engines made distribution cheap. Discovery, which was one of the hardest problems to solve, got solved because of the speed and reach the internet offered. AWS made software development cheaper, you did not need a boatload of capital to start a software company. Gartner is getting replaced by Capterra and G2 for the same exact reason of discovery is cheaper, as is distribution.

All the constraints that existed before to make sales the top dog in a company have been eroding over the years. These advances have made it a level playing field (for the most part). Information availability (G2, Capterra), near 0 cost of distribution and setup means that the only way a company can differentiate itself significantly from competition and win is through product.

The new role of engineering in product-led companies

Cloud computing has made CI/CD possible, and this rapid iteration helps create value immediately instead of long product cycles. Every new feature that is released is monetizable almost instantaneously. Your engineering and product organization is directly contributing to revenue in a measurable way. This is not just an account expansion, or user acquisition focused growth; Retention is also significantly affected by your product's quality. Retention is the first step to growth.

Engineering has always been an expensive talent in organizations. Whether it was for silicon chips or software, it was a scarce skill always in demand. The old paradigm of product development classified these skills as costs, making sense in that era. However, for product companies selling software and other digital goods, engineering should be seen as a lever for revenue generation.

Newer organizations, especially in software, still treat engineering as a cost and allocate resources based on the cost that is saved by deploying this skill across the organization. Thus we see 100s of companies building their own recurring subscription infrastructure when multiple SaaS companies exist to solve this problem. Non-customer facing development improves efficiencies within the organization, but allocating the same resources to customer-facing development could potentially have a significantly greater RoI if internal tooling is handled by other bought software or potentially spending as little time as possible in building internal tools (Non-customer-facing software).

What we think this means is that org and incentive structures need to change. It is not just a sales and marketing team generating revenue but also teams of product managers and engineers responsible for revenue growth. This may sound too harsh given how teams are structured now, but with better focus and newer org structures, this will only seem natural.

Our experiences and conclusion

We think it is time for companies to rethink their build vs buy decisions and consider product and engineering revenue generators. Opportunity costs in whatever form must also be taken into account while making these decisions. In the new age, the product will determine the winner, and it is essential to align your teams on this mission.

Our experience building Appsmith has yielded disproportionate returns by keeping engineering’s primary focus on customer-facing features and requests. We are seeing impressive growth over the last few months with pure product improvements and additions (support is included, of course, by our engineers!). Maybe we were lucky as we are building an internal app builder, and our team was forced to eat our dog food, but this is something that we believe has worked well for us, and we think other organizations should consider it more seriously.

If you have any questions, suggestions or feedback, please feel free to share it at akshay@appsmith.com

Cover Image Credits: Photo by Isaac Smith on Unsplash

Announcing the Import-Export Feature for Appsmith Applications
28
June
2021
Announcement

Announcing the Import-Export Feature for Appsmith Applications

Announcing the Import-Export Feature for Appsmith Applications
Vihar Kurama
0
 minutes ↗
#
features
#
engineering
#
open-source
#
javascript
Announcement

You have been asking for it, and we have developed it! The import-export feature is now out in the latest version (>v1.5.4) of Appsmith. With this, you can easily migrate apps from your self-hosted environment to Appsmith cloud or vice-versa.

At Appsmith, our users develop internal applications on the cloud, self-hosted installations, or even on local environments on their laptops, and it’s a pleasant experience in all cases. However, when looking to move the app from one environment to another, the only option was to rebuild applications… until now!

We’ve been asked multiple times on our community platforms for a quick way to migrate applications.

CleanShot 2021-06-25 at 01.28.11@2x.png
CleanShot 2021-06-25 at 01.25.51@2x.png
CleanShot 2021-06-25 at 01.30.57@2x.png

And then, we’ve created a feature request on GitHub!

CleanShot 2021-06-25 at 11.31.48@2x.png

Today we proudly ship the import-export feature to our community. With this feature, you can export the application as a JSON file and import it to any development environment in just a few steps.

We limit this functionality to only the organisation’s administrators to ensure that your database credentials, etc., do not get exposed to all the developers.

Want to try this out? Let’s see how mind-bogglingly easy this is!

Step #1 Export the Application

On your dashboard, open the overflow menu of the application you want to export from the source environment. Select the export option from the menu. This will download a JSON file with all the information about your application.

CleanShot 2021-06-28 at 08.16.28@2x.png

Step #2 Import the Application

Choose the organisation you want to import the application from the dashboard to the destination environment. Open the overflow menu by selecting the organisation name and select import. Upload the exported application JSON file.

Awesome, in just two simple steps, you should be able to migrate your Appsmith application!

Special credits to @abhvsn, who had worked hard on getting this feature out!

We appreciate each contribution and piece of feedback that you share. Join the community! Come chat with us on Discord, or jump in on Github directly.

Evaluating JS in the Browser for a Low Code Product
26
January
2021
Engineering

Evaluating JS in the Browser for a Low Code Product

Evaluating JS in the Browser for a Low Code Product
Hetu Nandu
0
 minutes ↗
#
engineering
#
performance
#
reactjs
#
js
Engineering

Appsmith is an open-source low code platform for developers to build internal apps and workflows.

In Appsmith, our developer users define business logic by writing any Javascript code in between {{ }} dynamic bindings almost anywhere in the app. They can use this while creating SQL queries, APIs, or triggering actions. This functionality lets you control how your app behaves with the least amount of configuration. Underneath the hood, the platform will evaluate all this code in an optimized manner to make sure the app remains performant yet responsive.

Let us take an example of binding a query response to a table widget.

It all starts with the binding brackets {{ }} . When the platform sees these brackets and some code in it, in a widget or action configuration, it will flag the field as a dynamic field so that our evaluator can pick it up later. In our example let us bind usersQuery to usersTable

Screenshot_2020-12-05_at_2.46.08_PM.png

Since we have added this binding in our tableData field, we will flag this field and store it in our widget config

// usersTable config
{
  "usersTable": {
        ...
        "tableData": "{{
            usersQuery.data
                .map(row => ({
                    name: row.name,
                    email: row.email
                }))
            }}",
        "dynaminBindingPathList": [
            {"key": "tableData"}
            ...
        ]
    }
}

In the background, our evaluation listener, always keeps a lookout for such events that would need an evaluation. For our example, this is a scenario that definitely needs an evaluation, so it kicks off our evaluator.

We pass on our current list of app data constructed in what we call as DataTree to the evaluator thread and patiently wait to hear back from it ⏱

// DataTree
{
    "usersQuery": {
        "config": {...},
        "data": [...]
    },
    "usersTable": {
        "tableData": "{{
            usersQuery.data
                .map(row => ({
                    name: row.name,
                    email: row.email
                }))
            }}",
        "dynaminBindingPathList": [{"key": "tableData"}]
    }
}

For performance reasons, we run our evaluation process in a separate background thread with the help of web workers. This ensures that evaluation cycles running longer than 16ms do not hang up the main thread giving the app bandwidth to always respond to user events.

Inside the thread, the event listener gets a wake-up call and gets to work.

  • Get differences: First it will calculate differences in the DataTree from the last time. This will ensure we only process changes and not the whole tree. In our example, we would see the usersTable.tableData has changed and usersTable.dynamicBindingPathList has a new entry. It takes each difference, filters any un-important changes, and processes the rest.
  • Get evaluation order with dependency map: It also maintains a DependencyMap between various entity properties. The evaluator will notice if any bindings have changed and recreate the sort order accordingly.For our example, we will infer that usersTable.tableData now depends on usersQuery.data. This means that the query response should always be evaluated before we can evaluate the table data and that whenever we see a change in the query response, we need to re-evaluate the table data as well
// DependencyMap
  {
      ...
      "usersTable.tableData": ["usersQuery.data"]
  }
  // Evaluation order
  [
      "usersQuery.data",
      "usersTable.tableData"
  ]
  • Evaluate: After creating an optimized evaluation order, we will evaluate the update the tree, in that said order. Evaluation happens via a closed eval function with the whole DataTree acting as its global scope. This is why we can directly reference any object in our DataTree in our code.
// Evaluator

  const code = `
    usersQuery.data.map(row => ({
      name: row.name,
      email: row.email
    }))
  `;
	const scriptToEvaluate = `
    function closedFunction () {
      const result = ${code};
      return result
    }
    closedFunction()
  `;
	const result = eval(scriptToEvaluate);
  • Validate and parse: We always want to make sure the values returned after evaluation to be in the right data type that the widget expects. The ensures the widget always gets predictable data even if your code has returned some errors. This is also needed for any function down the line in the evaluation order, if it refers to this field, will always get a reasonable data type to work with.

And that completes it. At the end of this, we will have a fully evaluated DataTree that we can then send back to the main thread and start listening for any new event to do this whole process again.

// Evaluated DataTree
{
    "usersQuery": {
        "data": [...] 
    }
    "usersTable": {
        "tableData": [...]
    }
}

Our main thread gets an event saying the evaluation is complete, with the new evaluated DataTree which it stores in the app redux state. From here, the widgets pick up their data and render it.

Screenshot_2020-12-05_at_2.46.22_PM.png

Summarizing our philosophy

  • Pull vs Push: While building a low code app builder for varied developers, we thought hard about how the written code works with the rest of the platform. We wanted configuration to be easy to start yet powerful when it needed to be. For this reason, we went with a Pull based architecture rather than Push. What this means is that in most places, you won't have to think about how the data will get to a field. You write code that pulls everything from the global DataTree and sets it to the field where you write it. This way the moment the underlying data changes, it get propagated to all the fields dependant on it and you as a developer do not have to orchestrate ui changes.
  • One-way data flow: Since we are built on top React.js and Redux, we strongly embrace the one-way data flow model. What this means is that you cannot set a table's data directly to that field from some other part of the app. If you do need to update the table, you will have to trigger the query to run, which will then cause the table to re-render with the new data. This helps the code you write easy to reason about and bugs easy to find. It also encapsulates each widget's and action's logic in itself for good separation of concern.