Creating multi-page apps

Learn how to share data between apps and create a multi-page experience.

Retool apps exist as single-page applications. You can arrange components together to organize your app's page into different areas of functionality—components like the Tabbed Container reduce visual clutter by showing users only what they need. As your app evolves and becomes more complex, you can separate functions even more.

A common approach for scaling apps built with JavaScript frameworks is to implement routing for additional pages. With Retool, you build separate apps and send data from one to another to create a multi-page app experience (e.g., passing a customer's email address from a CRM app to a Payments History app). This approach maximizes performance, reduces maintenance, and improves the user experience.

You can send data directly from one app to another using either URL query strings or localStorage. Query strings are best suited for smaller pieces of information, while localStorage can save larger amounts of data locally to the browser. As your apps become interconnected, you can create a shared navigation menu to improve the multi-page experience further.


Sharing data using URL query strings

Every app has a unique URL. You can append query strings to this URL and retrieve them using the urlparams object. There are two ways to pass data from one app to another with query strings:

  • Use event handlers to open an app and specify query strings to include
  • Manually construct a link to another app that includes query strings in the URL

Using Event handlers

An event handler acts in response to specified user interaction, such as a button click. The Go to app action opens another app and includes additional options to create query strings.

Using table data for query strings.Using table data for query strings.

Using table data for query strings.

Specify a name for the query string and a reference to some data to pass. For example, a query string value of {{table1.selectedRow.data.name}} would include the value for the name column from this table’s selected row.

Manually constructing a link

You can also link to an app with query strings attached to the URL. This method can be helpful if you need to link to an app differently or share data outside of Retool.

Copy the URL of the app you want to send data to, and add your query strings:

<a href="https://samples.retool.com/editor/5e31bf20-2861-11ec-9797-b304ca9072c9/Inventory?name={{table1.selectedRow.data.name}}">Open in new app</a>

Retrieving query string values

You retrieve any query strings appended to the app’s URL from the urlparams object. For example, you can dynamically include the value of a particular query string or display a placeholder if the value doesn't exist:

// Load a value from a query string

{{urlparams.name ? urlparams.name : 'No product submitted'}}

console.log(urlparams.name);
Using a query string value in a Text component.Using a query string value in a Text component.

Using a query string value in a Text component.


Sharing data using localStorage

localStorage is a flexible solution for temporarily storing data locally to the browser. All apps in your Retool organization have the same origin and share access to its localStorage. You cannot share data outside of your Retool organization using localStorage—use query strings if you need to accomplish this.

Considerations

Keep in mind the following considerations to avoid common pitfalls when implementing localStorage:

  • Prevent query loops. Avoid queries that write to localStorage which are triggered by changes to localStorage values. This can cause an infinite loop and impact your app's performance.
  • Assume apps are open in multiple tabs. It's common for users to have multiple apps—or multiple instances of the same app—open in different browser tabs. Consequently, an event triggered by a change to a localStorage value can cause performance issues because it occurs in every instance of the app.

Saving data

🚧

Overwriting data in localStorage

Saving a value to localStorage using a key that currently exists will immediately overwrite it. Use a naming convention if you intend to use localStorage with multiple apps.

Use localStorage.setValue(key, value) to save data as key-value pairs to localStorage. You can also save objects to localStorage if you want to share entire data sets rather than individual values.

// Save to localStorage

localStorage.setValue('app1name', table1.selectedRow.data.name);

localStorage.setValue('app1data', table1.selectedRow.data);
Saving table data to localStorage.Saving table data to localStorage.

Saving table data to localStorage.

You can use the Modal Browser to view localStorage and confirm that your app data was successfully saved. Click the Left panel button, located above the canvas, to open the Modal Browser. Expand localStorage to reveal the currently stored values.

Viewing data stored in localStorage with the Modal Browser.Viewing data stored in localStorage with the Modal Browser.

Viewing data stored in localStorage with the Modal Browser.

Retrieving data

Use localStorage.values to retrieve saved data from localStorage:

// Load a value stored in localStorage

{{localStorage.values.app1name ? localStorage.values.app1name : 'No product submitted'}}

console.log(localStorage.values.app1name);

// Load a value from an object stored in localStorage

{localStorage.values.app1data.name ? localStorage.values.app1data.name : 'No product submitted'}}

console.log(localStorage.values.app1data.name);
Displaying localStorage data in a Text component.Displaying localStorage data in a Text component.

Displaying localStorage data in a Text component.

Deleting data

We recommend you delete data from localStorage after retrieving it if it's no longer needed. Use localStorage.clear() to clear all localStorage data from your apps. You can also clear specific values by setting an empty value for a specified key:

// Clear localStorage

localStorage.clear()

// Set an empty value

localStorage.setValue('app1name', null);

Navigating between apps

If your users frequently use different apps, consider using the Navigation component to improve the multi-page experience. Menu items can run queries, link to external URLs, and open apps—including options for query strings.

You can also create a module—a reusable group of components and queries—containing your navigation menu to save time implementing it across your apps.

Adding a module to the Header frame.Adding a module to the Header frame.

Adding a module to the Header frame.

You create a module in much the same way as an app, and they can be added to any app in your organization. Select the Insert tab in the right panel, select Modules, then drag the module to the canvas.

Creating a module that contains a Navigation component.Creating a module that contains a Navigation component.

Creating a module that contains a Navigation component.


Did this page help you?