Introducing Shopify Polaris0:00
Polaris is a Shopify's toolkit for building user interfaces within the admin dashboard. It provides a common set of design guidelines and components that help developers create consistent and high-quality UX for merchants. It offers both CSS-only version as well as the React components, and it is recommended to use the React versions of the components, which is what we'll be using in this series. The documentation clearly outlines the design principles and best practices, so read through some of these pages when you're working on Shopify apps to help you build consistent UIs. Components page here lists the available components that we can use to build our application. So let's get started by installing Polaris React library in our application.
Installing Polaris React0:36
Components page here lists the available components that we can use to build our application. So let's get started by installing Polaris React library in our application. Let's head over to our code, open the terminal. We'll run vendor/bin/sail npm install @shopify/polaris --save-dev. Once the installation is complete, we need to run npm run dev. So we'll do vendor/bin/sail npm run dev. Let's close this out, and we need to import the Polaris styles within our index.js. So we'll open index.jsx, and we'll import the Polaris styles in here. So we'll do import { colors } from '@shopify/polaris/build/esm/styles';. Next we need to wrap our application within the PolarisProvider.
Wrapping with AppProvider1:17
So we'll do import, Shopify, Polaris, build, ESM, styles. Next we need to wrap our application within the Polaris provider. So basically we need to wrap this AppBridgeProvider within the Shopify Polaris provider. So we'll do AppProvider from Shopify Polaris, and we'll wrap it this way. And we can also pass the translations object to support the internationalization in our application. We're going to import the English translations and pass that in by default. So we'll do import ENTranslations from Shopify/Polaris/locales/EN.json. Let's take this and pass that in in here. Let's format the code, and we should be good to go.
Building Missing API Banner1:59
Let's take this and pass that in in here. Let's format the code, and we should be good to go. Now we're ready to start using some of the Polaris components. Let's render some sort of banner if the APIKey is not provided for whatever reason. Let's create a new component for that. So I'll open the project files here, open resources, JavaScript, and let's actually create a new directory here called components. Let's create a new component here. We'll call it something like MissingApiKey.jsx, and this component needs to render the Banner component.
We'll call it something like missingApiKey JSX, and this component needs to render the Banner component. So let's do const missingApiKey, and we'll render it here. And let's export default missingApiKey. We can use the Page and Layout components from the Polaris to sort of give it a layout and a bit of structure. So we'll render the Page component first. Then within the Page, we'll render the Layout component. And within the Layout, we'll render the LayoutSection component. And within here, we'll render the Banner components.
And within the layout, we'll render layout section component. And within here, we'll render the banner components. We can pass the title here. So let's set the title to Shopify API key is missing. And we can also set the status, which will give it a bit of styling. So we'll set the status to critical. And within this component, we'll provide some text. So we can say something like Shopify API key is missing from the application. Then within our app component, we can add a simple conditional here to check if the API key is provided or if it's missing.
Then within our app component, we can add a simple conditional here to check if the API key is provided or if it's missing. So we can do if the app bridge config API key is missing, then we can render the MissingApiKey component. Now in order to render the MissingApiKey component, we need to wrap it within the AppProvider from Polaris. So we'll copy this, put it here, and we'll render the MissingApiKey component this way. Now let's test this out quick. Let's open the browser.
Now let's test this out quick. Let's open the browser. We see the hello world, which is expected because API key is given. So let's now simulate it by maybe removing the API key from the .env file. So let's open the .env file, scroll down, we'll comment out the SHOPIFY_API_KEY, go back to the browser, and sure enough, we see the banner stating that SHOPIFY_API_KEY is missing. Great. Now I'm not going to spend a lot of time on the design and the UI because frankly, I suck at design. So bear with me as I struggle writing some React and JavaScript.
Creating Slider and Button4:28
at design. So bear with me as I struggle writing some React and JavaScript. In other words, don't expect FNC UI. So to start, we just need a number slider or number input that allows the user to enter the number of fake products that they want to create, and maybe a button that will actually trigger that action. Polaris does have a slider component. So we're going to use that. So if we go back to the Polaris documentation and scroll down in the components, we see the range slider in here.
So if we go back to the Polaris documentation and scroll down in the components, we see the range slider in here. So if we click on that, we can use this component to let the User select how many products they want to create. Let's click on which steps here that will show us an example component, allowing us to set the value of a specific increment in our slider. So let's scroll down, we can copy this component. Let's go back to the code, we'll bring back the Shopify API key. Let's go back to app.js and we'll render the slider instead of this hello world. First, let's render the page and layout components to give it a little bit of structure.
Let's go back to app.js and we'll render the slider instead of this hello world. First, let's render the Page and Layout components to give it a little bit of structure. So we'll do pageLayout, and we'll do layoutSection. And within here, we'll paste in the code that we copied. Let's import the RangeSlider from Shopify Polaris, we can set the label to numberOfProducts, we can set the minimum to 5 and maximum to 100. For now step we'll set to 5. And as for the value prop, we need to store this in some kind of state. Let's create options object and store the value of the slider in that object within the state.
Let's create options object and store the value of the slider in that object within the state. So let's scroll up here, we can do const options, setOptions equals to useState and we'll initialize the state with count with default value five. And then within here, we'll pass options.count this way. We also need to provide the onChange handler. So let's change this to handleProductCountChange. And let's create this function. So we'll do const handleProductCountChange equals and we'll use the useCallback hook here to basically memoize the handleProductCountChange function to help prevent unnecessary
So we'll do const handleProductCountChange equals and we'll use the useCallback hook here to basically memoize the handleProductCountChange function to help prevent unnecessary re-renders. So we'll do useCallback and we can use the setOptions function here to update our state. So we'll do setOptions, previousOptions, and we'll simply unpack the previousOptions and overwrite the count this way. Alright, the next step is to add the button that will trigger the action. Polaris also provides the Button component. So let's go back to the documentation, click on Button, let's select the primary here, scroll down and we can copy this component.
So let's go back to the documentation, click on button, let's select the primary here, scroll down and we can copy this component. As you can see, we can customize our button by passing some props here, we can set the size to large, micro or slim. It is set to medium by default. We can align it and so on. So let's go back to the code. Let's paste in the button in here right under the slider. Let's import this from the Polaris. We'll set the size to large and we'll change the text to something like create products.
Let's import this from the Polaris. We'll set the size to large and we'll change the text to something like create products and maybe we can even use the count from the slider state. So we can do create options count products. That way we can let the user know right away how many products they're about to create. Alright, let's go back to the browser and sure enough, we see the slider here and we have the button. If we increase the number of products, the number here changes as well. The thing is though, there is not much spacing here. Let's fix that by adding a form layout component.
The thing is though, there is not much spacing here. Let's fix that by adding a FormLayout component. FormLayout component from the Polaris basically arranges fields within it with standard spacing. So let's go back to the code and wrap this within the FormLayout component. Let's format the code, go back to the browser and sure enough, we have better spacing. Alright, let's now add the onClick handler to our button. So we'll do onClick and we should trigger some sort of createProducts function. So we'll do createFakeProducts. Let's create this function. We'll again use the useCallback hook to memoize it with the options as the dependencies.
Posting Data and Fixing Auth8:33
Let's create this function. We'll again use the useCallback hook to memoize it with the options as the dependencies. So we'll do it this way and pass options as dependency. And within this function, let's make the POST request to the products endpoint and console.log the response. So we'll do axios.post(products, options) as our data. And for the response, we'll simply console.log it for now. We also need to add this post route in our web.php routes file. So let's open the web.php routes file here. Let's actually get rid of this route to the /me because we no longer need that.
So let's open the web.php file here. Let's actually get rid of this route to the / because we no longer need that. And instead, we'll do Route::post products. And for now, we'll use the closure to return no content. But later we'll switch to using controllers. So we'll do response()->noContent(). Now this of course will not work because we don't have the Axios instance in here. When we were doing stuff with Blade, we were loading the bootstrap.js that was setting the Axios instance on the window object. So if we open the bootstrap.js, we had Axios right here, and we were configuring
the Axios instance on the window object. So if we open the bootstrap.js, we had Axios right here, and we were configuring it right here. Now we could import this bootstrap.js in our React component. But the problem is that we no longer have access to this window utils object to get the sessionToken. So to test this out quick, what we're going to do is that we're going to import Axios directly the same way we're doing it right here. So let's copy this, paste it in here. Let's open the browser, open dev tools, click Create, and we're getting 419 status code.
So let's copy this, paste it in here. Let's open the browser, open dev tools, click Create, and we're getting 419 status code. This is the standard CSRF token mismatch error from Laravel. Now according to Laravel Shopify's documentation, we should disable the CSRF protection due to conflict with the session token verification. The package uses the JWT session tokens and has the proper verification already built in. So the suggested solution is to basically disable the Laravel's CSRF check. We can do that by either commenting out the Laravel's CSRF middleware or simply open the VerifyCsrfToken and add wildcard here to exclude all the routes from the verifyCsrf.
We can do that by either commenting out the Laravel's CSRF middleware or simply open the verifyCSRFToken and add wildcard here to exclude all the routes from the verifyCSRF middleware. All right, let's go back to the browser. Let's click the button again. And this time we're getting 400 status error. If we inspect the response here, the response error states that the session token is invalid, which is sort of expected because we're not passing any session tokens. Remember within the bootstrap.js we have this interceptor right here where we're getting the session tokens from the window utils and passing that within the authorization header.
Remember within the bootstrap.js we have this interceptor right here where we're getting the session tokens from the window utils and passing that within the authorization header as the bearer token. But as I mentioned before, we're no longer able to do this because we don't have access to the utils object since we're not using Blade. Also if we go back to the browser and open the Telescope, we see that the authenticate/token requests are no longer being made. Those requests are needed when building non-SPA apps using Blade, for example, to handle session tokens. So even if we try to refresh the page here entirely and go back to Telescope and load
tokens. So even if we try to refresh the page here entirely and go back to telescope and load it, we see that it only makes this single request. There is no more /authenticate/token requests. So because we are in SPA mode, we have to get the session token another way. Let's do that in the next episode.
