New Shopify Certification now available: Liquid Storefronts for Theme Developers

Use React in app block theme extension

Solved
CymbalOfPeas
Visitor
2 0 2

Hello, I've just started getting into shopify development and completed Build App Example tutorial. It was a great tutorial, but really only covered the merchant back office flow. The app I'd like to build interacts with the online store. I've read through the docs and started using app blocks. 

 

My practice app is very simple. I have an input field on the product page, and I'd just like to sync the data to a draftOrder or checkout flow. I'm planning to post this data to an endpoint on submit. The part that's confusing me is the assets in my extension. I understand how to link schema settings and css in liquid, but is there no way to use React? It seems like I need to use vanilla javascript, and add that file to /assets/my-app.js.

 

I'm not new to development, but I am new to shopify. Maybe I'm missing something, but this doesn't feel right needing to import javascript like this? It also seems like it's not encouraged to use ScriptTag anymore. Any clarification or resources on this would be much appreciated!

 

Just looked into Dawn a bit more and seems like I'll have to go vanilla js:
https://github.com/Shopify/dawn/tree/main/assets 

 

I've also read through:

Accepted Solution (1)
ozzyonfire
Shopify Partner
47 2 16

This is an accepted solution.

Just in case you haven't solved this yet. Is is possible to use React within an extension. 

 

You can use tools like webpack and babel to bundle up your react app into a single file (i.e. bundle.js). Then in your block, just include that one file. 


Your app-block.liquid file may look something like this.

<div id="container"></div>

{% schema %}
  {
    "name": "React Block",
    "target": "section",
    "javascript": "bundle.js",
    "settings": []
  }
{% endschema %}

And then in your `src` directory, you can create a react app file, like index.js

import React from 'react';
import { createRoot } from 'react-dom/client';

const container = document.getElementById('container');
const root = createRoot(container!);

root.render(<h1>Hello World!</h1>);

You will need to configure webpack to bundle react apps appropriately, but there are plenty of tutorials out there on how to do that.

View solution in original post

Replies 43 (43)
ozzyonfire
Shopify Partner
47 2 16

This is an accepted solution.

Just in case you haven't solved this yet. Is is possible to use React within an extension. 

 

You can use tools like webpack and babel to bundle up your react app into a single file (i.e. bundle.js). Then in your block, just include that one file. 


Your app-block.liquid file may look something like this.

<div id="container"></div>

{% schema %}
  {
    "name": "React Block",
    "target": "section",
    "javascript": "bundle.js",
    "settings": []
  }
{% endschema %}

And then in your `src` directory, you can create a react app file, like index.js

import React from 'react';
import { createRoot } from 'react-dom/client';

const container = document.getElementById('container');
const root = createRoot(container!);

root.render(<h1>Hello World!</h1>);

You will need to configure webpack to bundle react apps appropriately, but there are plenty of tutorials out there on how to do that.

CymbalOfPeas
Visitor
2 0 2

Thanks! Ended up realizing this was path, but thank you for you reply! Hopefully it will help out someone else with a similar question.

tanmaykejriwal
Shopify Partner
50 1 5

There is no src directory inside the extensions/extension-name

 

TK
ozzyonfire
Shopify Partner
47 2 16

To clarify, I have a separate source folder outside of my extension folder. This is where my React source code lives. Then I configure webpack to build into the "js" folder of my extension. And I reference this file in the app-block.liquid file (see above).

Jamflynt
Shopify Partner
23 0 12

I'm a little late to this party but I am currently trying to do the same thing. @ozzyonfire would you happen to have any tutorials or examples to accomplish this you could point me towards?

oyong17
Visitor
2 0 1

Good day Bro. I tried to follow your instructions and I created separate folder for the ReactJS files. but I doesn't connect with the liquid file to React JS folder, even if I am calling the Dom Id of element and imported the bundled JS file in the app block section.

here's the code bro. kindly enlighten us more @ozzyonfire on why they does not connect.


oyong17_0-1687746767529.png

 





oyong17_1-1687746784379.png

 

oyong17_2-1687746797984.png

 

muazkhan123
Shopify Partner
1 0 0

Watching you very closely as I am trying to do the same thing. Did you get any solution?

iskurbanov1
Shopify Partner
6 1 2

Did you build/bundle the React app? 

ozzyonfire
Shopify Partner
47 2 16

Hey! Hopefully I can help you out. 

 

I am just using the shopify-cli to configure the extension. The CLI will generate all the necessary folder structure and files for an app extension (theme app extension). 

 

I basically followed this tutorial to get up and running.

 

Once you have that going, you should be able to setup a preview which renders your theme on your dev store and you can just drag and drop in your theme app extension. It will even hot-reload when it detects a file change in your extension directory. 

 

Once you have that working and you can see your changes in preview, then you can create a sibling folder next to your extension (I named mine "[extension-name]-dev").

 

This is where your react source code lives. You just build your react app in this file and configure webpack to build your react app out to a single file (usually in a "dist" folder called "main.js" or similar). 

 

Then just copy this file to your "js" folder in your app extension and it should all start working.

 

Webpack can be a little finicky to setup and there are all sorts of extensions and plugins for managing your CSS and other stuff, but it's extremely powerful.

 

Hopefully that helps you get started! Let me know if you still have questions and I will do my best to help!

 

 

oyong17
Visitor
2 0 1

wow. Thank you very much. now it enlightens me.

Peterpot
Shopify Partner
4 0 0

Hi @ozzyonfire ,

 

I followed the references you provided to create a Shopify app and theme extension and started a vite react typescript project in a new folder inside the extensions folder.

 

I configured the vite.config.ts file to be like this:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  build: {
    rollupOptions: {
      input: {
        app: './src/index.tsx',
      }
    }
  }
})

 

I did get a .js file under the dist/assets folder and put the index-c7e05d32.js file and the index-d526a0c5.css file inside the theme extension project's assets folder. However, when I added the theme extension to the Dawn store, I still see the default star rating theme extension. Am I missing any steps here?

ozzyonfire
Shopify Partner
47 2 16

It looks like you are using Vite to compile and bundle your react project. I don't have a ton of experience with Vite, but I will try to help... React needs a div element to hook into so that it can inject the react app into the DOM. 

 

I'm assuming your vite project has some sort of index.html file? This is how you app actually gets into the DOM and onto the page. 

 

You need to make sure that your app-block snippet (.liquid file) acts as this index.html. This is where the javascript source is loaded from and you need to set up the proper structure for react to inject itself into. 

 

If you share some of your project setup, I can try to help more.

codernex
Shopify Partner
2 0 0

I followed all the steps but it's not working in my case?
Can you please help me out

codernex_0-1690129100158.pngcodernex_1-1690129125017.png

 

ozzyonfire
Shopify Partner
47 2 16

I didn't load my assets in via a <link> element (although, I think somewhere in the docs it does say this may be possible?). 

 

Instead, I just referenced the bundle.js from the schema off the app-block itself. I think the structure is "javascript": "bundle.js" and you just make sure "bundle.js" is in your assets folder. 

 

I think the asset_url liquid transform you are using may actually reference the "theme" asset folder, which isn't necessarily what you want.

 

You can see an example of the schema here; https://shopify.dev/docs/apps/online-store/theme-app-extensions/extensions-framework#example-app-blo...

codernex
Shopify Partner
2 0 0

Finally i got it thanks bro

jlogey94
Shopify Partner
9 0 1

Could you provide steps on how you achieved this please?

 

jlogey94
Shopify Partner
9 0 1

Could you provide a screenshot of the folder layout with files for the extension please?

Also what do you mean by this "create a sibling folder next to your extension (I named mine "[extension-name]-dev"). This is where your react source code lives. You just build your react app in this file and configure webpack to build your react app out to a single file (usually in a "dist" folder called "main.js" or similar)" here you mention building react app in two different places, do you create a bundle file and thats it or is there another file also needed?

 

Any help would be much appreciated. I have created a custom app with a fair amount of moving parts and don't have the time to rewrite it in liquid/js.

ozzyonfire
Shopify Partner
47 2 16

What did you build your app in? Is it in React?

 

If you are feeling stuck, follow this tutorial - https://shopify.dev/docs/apps/online-store/theme-app-extensions/getting-started

 

You keep saying your "app" but what is your app built in, is it an embedded app? react app? something else? If it's an embedded app (used for the shopify admin section) then it's definitely not going to work as a theme app-extension. 

 

 

jlogey94
Shopify Partner
9 0 1

I have a react app which calls external api's and displays data to the user. It is currently installed on the merchants store and I thought there would be a setting or configuration in shopify admin to allow direct access to the app from the store but that's not the case. I have created a theme extension which calls a proxy to get data but if I continue down this route I will have to rewrite the app in js and liquid or as you have shown on here I could bundle it and reference it on my extension in an app block. I would just like some pointers to folders and files that should be in them and ways to build?

jlogey94
Shopify Partner
9 0 1

Hi,

 

I have been stuck on this for some time. I have a custom shopify app which is deployed and working but I need to embed it in a theme extension so I can display it in the clients shopify store. What you have described above is for embedding a new react app in a theme but what about an existing app which makes calls to external api's?

I have tried building the app using webpack/babel and then copying it to the extensions asset folder and then referencing it in the liquid file for the block but it's not working. Does all my app code need to be sitting inside another folder within extensions? 

Jamflynt
Shopify Partner
23 0 12

You should be able to accomplish it the way you described; your app code should not need to be in the extensions folder alongside the block. (in fact it probably shouldn't as there is something like a 10MB size limit for these and Shopify is very strict about the extensions folder's architecture).

All you should need in your assets folder is your app's static js and css files. Just be sure to reference it correctly in your liquid file schema. It should look something like: 

 

 

<div id="app-root"></div>

{% schema %}
{
"name": "ReactApp",
"javascript": "index.js",
"stylesheet": "index.css",
"target": "section",
"settings": []
}
{% endschema %}

 


That should work assuming it's packaged correctly. 

jlogey94
Shopify Partner
9 0 1

Ok thanks for you reply, what's the purpose of the app root div should something in my app be targeting that? Also if you have any advise for packaging or refs to useful docs for setting this up that would be greatly appreciated.

Jamflynt
Shopify Partner
23 0 12

Yes your app will need something to target since the liquid file is essentially taking place of the index.html in the extension (to my knowledge). So wherever you use ReactDOM to render your app just createRoot on the element you want to target. 

My advice would be to look at Vite: https://vitejs.dev/guide/why.html 
And hit up the React Docs if you are having trouble getting started: https://react.dev/learn

There is no real built in way to do all this so if you find something better for your needs that'll be the way to go. It's all trial and error. My understanding of app blocks is that this isn't necessarily what they are made for. 

jlogey94
Shopify Partner
9 0 1

I'm getting issues when building with webpack for certain scripts. Seems like I'm just constantly chasing different errors. Would it be easier to copy my app code into the extensions folder and effectively replicate the code?

Jamflynt
Shopify Partner
23 0 12

Wish I could say the chasing errors thing had an easy fix but that really is just kinda of the name of the game while figuring this out.

I would not put anything into the extension folder that was not an extension. Shopify doesn't seem to like that and keep in mind the size limit. Be sure to look at the architecture docs for Theme App Extensions: https://shopify.dev/docs/apps/online-store/theme-app-extensions/extensions-framework

And also just the overview to gain better understanding of what the true purpose of theme app blocks: https://shopify.dev/docs/apps/online-store/theme-app-extensions

I really would look at Vite as I mentioned above for your build. We've had success with it. 

iskurbanov1
Shopify Partner
6 1 2

I've put together a template on building a theme extension app using React and Tailwind CSS, hopefully this will help! Check it out here: https://github.com/iskurbanov/theme-app-extension-react

jlogey94
Shopify Partner
9 0 1

I managed to get it working through trial and error. Better documentation is needed on this kind of development. Hopefully the above helps others.

Jamflynt
Shopify Partner
23 0 12

Yeah the documentation for Shopify seems to be lacking across the board. Hopefully it's just hold over from their switch to 2.0. I only started working with Shopify 3 months ago so I am unaware if this has always been an issue (however some posts in here and on StackOverflow would lead me to believe it is). 

@iskurbanov1 Your course looks awesome. The community needs more people like you creating these type of learning experiences.

iskurbanov1
Shopify Partner
6 1 2

Yeah the docs give basic use-cases but since the Shopify ecosystem is so huge and always evolving/changing I can image it's hard to cover everything. 

Thanks, I appreciate the kind words!

 

I also added a blog post on how to set everything up:
https://dev.to/iskurbanov/shopify-app-theme-extension-with-react-tailwind-css-3n9e

jamesongamble
Shopify Partner
2 0 2

Thanks for sharing this! If anyone is using Remix for their embedded admin app, but want to use @iskurbanov1's vite dev/build/deploy process for bundling a react theme extension within the same repository, I merged his logic for the extension into the Remix fullstack template: 
https://github.com/jamesongamble/shopify-remix-vite-extension



iskurbanov1
Shopify Partner
6 1 2

Wow amazing job! Thank you, will keep this in mind if I end up migrating an app to Remix. 

arnav98
Shopify Partner
24 1 5

Hi @iskurbanov1, I wanted to know a couple of things -

  1. Will this setup have hot-reloading while developing the React app, or do I need to build the React app every time I make any changes?
  2. Will this have access to Liquid objects, for example I am using shop id in my backend calls, will I have access to those in my React app?
Mittlus
Shopify Partner
1 0 0

If anyone needs a more detailed explanation, I've created this article on Medium, which describes how to inject React (with Tailwind) into a Shopify theme app extension by using Webpack.

manfa
Shopify Partner
4 0 0

Everything seems to be great, but I'm wondering if there is a possibility to directly use block settings and translations located in the /locales directory in theme-app-extensions in the React code?

 

For example:

  1. I would like to be able to define the color of a certain element.
  2. I would like to use the translation .json files located in the /locales directory.
<div id="container"></div> 

{% schema %}
{
"name":"React Block",
"target":"section",
"javascript":"bundle.js",
"settings":[
{
"type":"color",
"id":"color_id",
"label":"Color",
"default":"#ff0000"
}
]
}
{% endschema %}

 

 

Jamflynt
Shopify Partner
23 0 12

I may be misunderstanding your question but to define the color of a certain element you could just use App Block Schema's and then pass the settings into the react app via data attributes on the root div. We've used this to accomplish several settings on within a React App. 

As for the translations, I've not done this but I don't see why you wouldn't be able too. I'd imagine it'd be part of the settings somewhere. 

manfa
Shopify Partner
4 0 0

Thanks @Jamflynt for the answer. Yes, it seems that it can be achieved by passing the data in data-attributes. I will test it. It would probably look something like this?

 

<div
id="react-container"
data-theme-color="{{ settings.color_id }}"
data-theme-title="{{ 'title' | t }}"
data-theme-label="{{ 'label' | t }}"
data-some-other-translate="{{ 'otherTranslate' | t }}"
>
</div>

{% schema %}
{
"name":"React Block",
"target":"section",
"javascript":"bundle.js",
"settings":[
{
"type":"color",
"id":"color_id",
"label":"Color",
"default":"#ff0000"
}
]
}
{% endschema %}

 

But I have a second question. How to use React in case we have several Liquid blocks? I understand that for each block it would be a kind of React micro-frontend each bundled to separate file? How would that work?

Jamflynt
Shopify Partner
23 0 12

Looks good to me. Only thing I see is here: 

data-theme-color="{{ settings.color_id }}"

Should look something like this in my experience: 

data-theme-color="{{ block.settings.color_id }}"

Anytime you reference an App Block setting you just need `block` in front of it. 

As to your second question, we've had success having our React App living in a separate folder outside of the extensions folder (Shopify is very picky on its structure) and creating an npm command to compile and push the bundled app to the appropriate locations inside of the extensions folder. 

Then just continue to add other Liquid blocks as you see fit and need. Just be aware that for App Extensions, Shopify has a limit of 10MB for Liquid files across the whole extensions folder. 

manfa
Shopify Partner
4 0 0

To clarify, do you mean that you have one React App situated outside the extensions directory? I'm having trouble understanding how this setup would function with multiple Liquid files.

 

My aim is to create a variety of independent Liquid blocks that can be integrated into different pages. Consequently, in my opinion, each block should be associated with a distinct React App, or at the very least, a different React Component.

 

For instance:

  1. Star Rating Liquid (React App A) -> Implemented on page A
  2. Additional Customer Information (React App B) -> Implemented on page B
  3. Customer Custom Coupons (React App C) -> Implemented on page C

These are merely illustrative examples, but I'm eager to understand if this approach is correct and it should be achieved with only Components in one React App.

 

Shopify has a limit of 10MB for Liquid files across the whole extensions folder. 

Yes, we are aware of Shopify's limits for this. We have small amount of functionalities, so we should not exceed this limit.

 

Jamflynt
Shopify Partner
23 0 12

For our purposes we are only using one React app that is populating one App block so yeah we have only one situated outside of the extensions folder. We also have several other App blocks inside of that Theme-app-extension that are not talking to a React app. 

Keep in mind, you can only have 1 theme-app-extension per App but that theme-app-extension can have up to 25 App blocks in the Blocks folder. 

If you had multiple apps, I'd assume what you have laid out would work. You would have each one build and populate (something you would set up in your package.json file) an individual App (Liquid) block in the Blocks folder in your extensions directory within the Shopify App. Shopify does not allow anything outside of this extensions file structure to live inside of the extensions/theme-app-extensions folder, so just be aware that the apps would have to live somewhere outside of that. 

Also, unless I am misunderstanding, you could probably get away with having a single react app that renders a specific component depending on where you've embedded the block in a Shopify page. You'd need to research that though. 

mqasim
Shopify Partner
3 0 0

i read all the conversation but still m confused  kindly guide me ..

 i have created a remix app using the cli3 and after that i also created a theme extension as well which i a block app to render a button in the product page and in the remix app i created a model using the polaris and i want to show the model which i created in the remix app to be shown when the user click on the button which i on the prouduct page here is the SS of what i did till now ..

mqasim_0-1701703710265.pngmqasim_1-1701703736990.png

 

mqasim_2-1701704317271.png

 

 

Jamflynt
Shopify Partner
23 0 12

Keep in mind Polaris is for Admin experiences only in Shopify, not client side/customer facing experiences. The base React stuff that is created when you create the App template is for this Admin experience and cannot be used in the theme-app-extension.

To get a modal to show up after clicking a button on your PDP, you'll have to create and compile a separate/new React application that works within the confines of your store or use JavaScript and Liquid inside the extension. The later is what is intended to be used with Theme-app extensions so if you can make that work, that would be the way to go.

mqasim
Shopify Partner
3 0 0

i have created the theme app extension (block app)  and with the help of extension I'm showing  a button with the label of " Cash On delivery  " and i want to show the model with the form which i have created in the app , ok i got it that polaris is for the admin , but can you please guide me in a simple way or get any reference , I'm creating a cash on delivery app 

Jamflynt
Shopify Partner
23 0 12

I'm not totally clear on what you're asking, but it sounds like you'll want to recreate the form you created for the admin in the app block to get it to show up. Beyond that, familiarize yourself with the theme-app extension framework and the rest of the documentation surrounding apps, as well as the various API's you'll have access too to make your block work. 

Also keep in mind that Shopify has a Cash On Demand option available as an option in their checkout. You may also want to familiarize yourself with Shopify Functions and Checkout Extensions. This may be better suited to what you are trying to do.