Re: Use React in app block theme extension

Solved

Use React in app block theme extension

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
49 2 17

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 69 (69)

ozzyonfire
Shopify Partner
49 2 17

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
60 1 6

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

 

TK
ozzyonfire
Shopify Partner
49 2 17

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

greekfreak_034
Shopify Partner
3 0 0

Hello! @ozzyonfire Thanks for the insights on how to use react on shopify extensions. I've installed an image editor library on the extension, do you have idea why this error occurs ? Thanks!

greekfreak_034_0-1708841146242.png

Trying to add a sticker (.png) from my s3 bucket.

Joy33
Shopify Partner
3 0 0

And how you have your architecture or structure, cause when I created the app, was installed with Vite configuration and I'm getting few errors trying this ?!

Jamflynt
Shopify Partner
38 0 20

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 3

Did you build/bundle the React app? 

ozzyonfire
Shopify Partner
49 2 17

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
5 0 1

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
49 2 17

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
49 2 17

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
49 2 17

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
38 0 20

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
38 0 20

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
38 0 20

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. 

SylviaZ
Shopify Partner
6 0 0

Hi, I am developing a Shopify theme extension and I encountered a file size limit issue with JS files. I have used Vite's manualChunks to split my JS files, but the react-dom.js file still exceeds the 10KB limit. Do you have any suggestions? Thank you!

SylviaZ_1-1717748824816.png

Jamflynt
Shopify Partner
38 0 20

That asset size limit is part of Theme Check in the CLI. You can disable it.

That screenshot only appears to show the vite output as well, this limit should only apply to javascript files in the "extensions/your-theme-app-ext/assets" directory unless I am mistaken. 

SylviaZ
Shopify Partner
6 0 0

Thanks for your reply, disabling is effective.

You are right, The screenshot is I created a Vite project and dragged the .js files to the Shopify extension/assets. Now I have integrated them into a single project.

iskurbanov1
Shopify Partner
6 1 3

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
38 0 20

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 3

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 3

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

arnav98
Shopify Partner
26 1 7

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?
Ken38
Shopify Partner
6 0 2

I used it your git report for the theme extension but It's completely deployed there is not showing me any content when I use the extension in Shopify store it's showing nothing can you help how I can do that

I'm new in Shopify extension I don't know more about extension

Jamflynt
Shopify Partner
38 0 20

If you haven't done so (since your new) you'll need to familiarize yourself with the CLI commands to be able to deploy the app and build the extensions: https://shopify.dev/docs/apps/tools/cli/commands. You'll also need to install the App to your store via your Shopify Partners account if you haven't already done so as well. 

Also be aware that hot reload is a mixed bag. It only works in Development stores and inconsistently so.

Ken38
Shopify Partner
6 0 2

Ken38_0-1704897425669.png

 

Ken38_1-1704897485398.png

 

Extension is showing in dev store but it's not showing the content as you can see I write the simple content but it's not showing in mystore

 

Jamflynt
Shopify Partner
38 0 20

Can you show any code or errors? 

Ken38
Shopify Partner
6 0 2

Ken38_0-1704946997455.pngKen38_1-1704947011647.pngKen38_2-1704947026513.pngKen38_3-1704947037230.png

 

 

Ken38
Shopify Partner
6 0 2

Can you check and reply me pls let me know if I do wrong

Jamflynt
Shopify Partner
38 0 20

I don't see anything wrong with your code from what you shared. Double check your file paths and look at your console in the browser. See if that "Home" console log shows up. Add more console logs as necessary to troubleshoot. Also, does the the div show up at all in the HTML when you inspect it?

Also double check your deployment version in Partners and make sure it's the right one.

arnav98
Shopify Partner
26 1 7

Hey @Jamflynt , I wanted to understand how are you dealing with assets like images?
For e.g. - The React app I've set up outside in another folder is working correctly and is deployed too, but I'm facing issues displaying the images which are stored in the /assets folder inside the theme-extension.
Since earlier my app was entirely written in liquid, I could just use the Liquid filters and host my images on Shopify's CDN and reference them directly. Now the images which are in my React app are deploying on the Shopify CDN. But since I can't the theme-extension folder now, the path to the images is not there.

How can I possibly use with the images in my "bundle.js" which is correctly compiling in the /assets folder?

Jamflynt
Shopify Partner
38 0 20

We have a few images stored in an assets folder in the src of our React app that we reference. These are small things like icons that are compiled with the React app. 

The rest we have in blob storage and reference those urls.

There would be some serious size limitations on any files you'd be bundling up with the application. But if your app is meant for a single store only I'd imagine you can still use the Shopify CDN ; just copy the URL from the Admin and reference it in your app. If your app is meant for multiple stores you'd probably need to look into something like blob storage for your image assets needs.

Mittlus
Shopify Partner
4 0 1

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.

densekernel
Shopify Partner
8 0 0

Thank you - this is a very good article.

 

We are working on a theme app extension - The extension will have multiple blocks using common code.

 

In fact this is part of the motivation to move to something like React to leverage the imports.

 

If we have two blocks:

 

  • foo.liquid
  • bar.liquid

 

In the block template we are linking to the bundled React app like this:

 

<span>This is Liquid</span>
<div id="container"></div>

{% schema %}
  {
    "name": "React Extension Tutorial",
    "target": "section",
    "javascript": "react-extension.js",
    "settings": []
  }
{% endschema %}

 

Would you link to the same "react-extension.js" from both "foo.liquid" and "bar.liquid"?

densekernel
Shopify Partner
8 0 0

I followed the exact steps in the article

 

I was able to get the React app to render the span tag:

 

Screenshot 2023-12-18 at 16.03.49.png

However once I switch index.js back to trying to import the App component

 

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <App />
);

I now get a Reference Error for React:

 

Screenshot 2023-12-18 at 16.04.21.png

 

This is happening on the call to React.createElement: Screenshot 2023-12-18 at 16.06.57.png

 

It's strange because the minified production React is definitely in the bundle:

 

Screenshot 2023-12-18 at 16.04.39.png