Use React in app block theme extension

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:

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.


{% 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(# Hello World!);

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

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

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

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?

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.

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

Did you build/bundle the React app?

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).

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!

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

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?

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

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.

I didn’t load my assets in via a 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-block

Finally i got it thanks bro

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?

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:


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

That should work assuming it’s packaged correctly.

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.

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.