This is a second post that walk you through building a DApp, using truffle, React, Next.js and MobX. Blockchain As a quick reminder we’re going to use the Blockchain ( ) as an efficient way to handle the mapping of a user’s and their favorite tv shows. Ethereum The app displays a list of shows coming from unofficial API. Split into three categories: Fresh, New and Popular. rotten tomatoes A special section in the app “Bookmarks” displays a list of user’s favorite shows which are currently stored on the Blockchain. Users are able to add or remove shows from their Bookmarks section. Every time a user adds or removes a show a Smart Contract function is invoked and the change is stored on the Blockchain. The front-end app is a server side rendering React app powered by , for state management we’ll use M X, styling and layout will come from the awesome project and in order to interact with the Blockchain we’ll write a Smart Contact in solidity, write tests for it in JavaScript and deploy it locally using . Next.js ob tachyons truffle In the , we went over the implementation of our Smart Contract that acts as our app backend logic and storage. In this post we’ll focus on building the UI using React and how we can invoke actions on our Smart Contract from within the browser. previous post In more details in this post I’ll go over: Setting up The Development Environment Writing our Backend API Writing our React component Writing our MobX store to handle app state changes. Writing our BlockChain service that will invoke our Smart Contract public APIs. Setting up The Development Environment Make sure you have node, git and nvm install before starting this. First we need to install TestRpc and Truffle: npm install -g ethereumjs-testrpc npm install -g truffle Now clone the app and install the dependencies: //clone the repogit clone :liors/tvdapp.git git@github.com // Navigate to within the directorycd tvdapp //install dependenciesyarn install //start the development serveryarn dev In a new terminal window start a local Blockchain network: testrpc Now we need to compile and migrate our Smart Contract run: yarn run blockchain Once you run all the above commends you can open your browser at and see a local version of the app. http://localhost:3020/tv/fresh Our Backend API Next.js comes with default express configuration. In some cases that’s fine, in our case I wanted to add routes to our API requests so I’ve used a custom express server. Under /server you can find two files index.js and api.js Let’s go over index.js Our API has 3 end-points: /api/shows/new /api/shows/popular /api/shows/fresh All of them uses the same api.get function we exports from api.js. In addition we alias some get requests to our main /tv/fresh route, so when a user visits / or /tv we redirect him to our /tv/fresh page. All other requests i.e., ‘*’ will be handle by next.js default route. The last part of our backend code is fetching the content from and enrich the return data with images coming from . rotten tomatoes tvmaze Let’s go over api.js We export a get function that receives a type. We then making a request and map the result over to generate an array of titles and urls. IMO provides better quality images, so let’s enrich our API by getting for each show an array of images. tvmaze Async/await syntax helps us avoid nested callbacks and hopefully to create a more readable and clean code. Our get function returns a Promise that includes an array of JSON objects, each includes a title and an img object. Our React components Next.js provides a very simple routes API. You only need to create a pages folder and each file under this folder will become the main react component rendered for this route. For example /pages/index.js will be your app homepage i.e., the default route /. In our case the main page route is under /pages/tv/fresh.js Next.js also provides a way to fetch data on both server and client by introducing a new life cycle function called . When implementing it we must return a that resolves to a JavaScript object, which then populates the component’s getInitialProps Promise props. We start by invoking our API — /api/tv/fresh and initiating our store with the result shows. The function then return our component props: shows and if we are rendering the results on the server or not. Our render function is quite simple — we simply render a Page component and pass it two props: type and store. All our pages/routes look very similar, the differences are the page type and store which contains the relevant shows for the given type. Let’s look at our Page component. This component uses two additional components — our app navigation and the grid of shows. The selected page is the current prop type. Our render function is wrapped with a MobX provider as this is our main component of the app. This component has another responsibility. Only when running on the client i.e., in React’s function we setup our web3 instance, once this is done we make a request to our Smart Contract to get the already bookmarked shows. Once this request is resolved we update our store which cause our app to be re-rendered if needed. componentDidMount Lets looks at our main UI component shows.js Our render function uses a `square title subtitle` layout from . In order for our app to recognize these css classes (for example cf, w-100, pa2-ns etc) we need to include tachyons css file. tachyons.io Next.js provides a way to customize the main html that is being generated by the server by creating a _document.js which let you return a chunk of html that includes a head tag. In our cases we’ll set the viewport and include some external resources we use — font, css files and the web3 library. <Head><meta charSet='utf-8' /><meta name='viewport' content='initial-scale=1.0, width=device-width' /><link href='//fonts.googleapis.com/css?family=Roboto' rel="stylesheet" /><link href='//cdnjs.cloudflare.com/ajax/libs/tachyons/4.8.1/tachyons.min.css' rel='stylesheet' /><link href='//cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css' rel='stylesheet' /><script src='/static/js/web3.min.js'></script></Head> Back to our shows component — once we render our shows we need to display a different SVG for shows that are already bookmarked vs those that are not. We do that by looking at our bookmarked shows array in our store: isBookmarked = show => some(this.props.store.bookmarkedShows, show) some is a function that checks if in this case identity returns truthy for element of in our case our list of shows. lodash predicate any collection Now we need to implement the Bookmark action. We do that by wrapping the title/subtitle/bookmark SVG elements w/ an anchor tag and define an onClick function on it: handleBookmark = show => this.props.store.bookmark(show) Our last react component is the Notification component that gives to the user an indication that a show is added/removed from the Blockchain, you can find it under /components/notification.js Our MobX store to handle app state changes As we saw in our components implementation we do not have any calls to re-render our components or fetch requests to get/change data. Our MobX store handle this for us and provide us w/ the core APIs our UI needs. this.setState() Our store supports the following actions: bookmark — this acts as a toggle for bookmark/remove action to our UI. setBookmarkShows — this set the initial bookmark shows coming from the Blockchain. hideBookmarkNotification — this help hiding our notification component once needed. Let’s look in more details at our bookmark function. We first check if the provided show is already bookmarked — if not we use our blockChainService’s bookmarkContract function. As an argument this function gets a JSON that represents the show to bookmark— this JSON will be then stored on the Blockchain. Once the request is resolved we add the show to our observable shows array, turn on the notification flag and set the proper type of action — this will help the notification component to display the proper text. To remove/reject an already bookmarked show we call rejectBookmarkContract and filter out the show from our observable shows array. Our BlockChain service that invokes our Smart Contract public APIs We got to the last part of our app, the service that uses ethereum’s web3 to invoke remote function on our Smart Contract. Let’s look how the service getBookmarks is implemented: let getBookmarks = function () {return new Promise((resolve, reject) => {let instancegetBookmarkInstance().then(result => ({instance} = result)).then(() => instance.getBookmarks.call()).then(bookmarks => {resolve(bookmarks && JSON.parse(bookmarks.toString()))})})} In order to invoke any Smart Contract function, we need to get the available web3 instance. We do that by importing our BookmarkArtifact and the contract function from truffle-contract import BookmarkArtifact from '../build/contracts/Bookmark'import contract from 'truffle-contract' Then we provide the contract function our artifact and set it’s Provider to the current web3 instance current provider. const Bookmark = contract(BookmarkArtifact)Bookmark.setProvider(web3Instance.currentProvider) Once we did that we can get the accounts and return the deployed instance for the first one. web3Instance.eth.getAccounts((error, accounts) => {const account = accounts[0]Bookmark.deployed().then((instance) => {resolve({ instance, account })})}) Ok, so back to out getBookmarks function. Once we have an instance we can invoke our Smart Contract public APIs. In this case we need to get our bookmark shows i.e., call getBookmarks instance.getBookmarks.call().then(bookmarks => {resolve(bookmarks && JSON.parse(bookmarks.toString()))}) The result will be a string that we parse and transform into a JSON object. Bookmarking a show looks very similar. We first get an instance and then call our bookmark function, in this case we need to provide some addition information — from which account this action happens. instance.bookmark(JSON.stringify(blockchainBookmarks), { from: account }).then(showId => instance.getBookmarks.call()).then(bookmarks => {resolve({ data: JSON.parse(bookmarks.toString()) })}) That’s it our app is complete. To summarize, we’ve been using React, Next.js, MobX and truffle to build a server side rendering React DApp. I hope you can take this simple setup to start your own development on top of the Blockchain. The complete code is available on , if you like it please start the repo! github A live version of the app is deployed — Please make sure your browser can run DApps, I’ve been using chrome extension. here MetaMask Thanks for reading. Hope this is helpful.