From 8509a7e52fa2c422e228451537903460980641ed Mon Sep 17 00:00:00 2001 From: Vojtech Simetka Date: Tue, 16 Feb 2021 09:40:51 +0100 Subject: [PATCH 1/2] feat: tutorial create dapp in react --- docs/tutorials/create-dapp.md | 424 ++++++++++++++++++++++++++++++++++ sidebars.js | 8 + 2 files changed, 432 insertions(+) create mode 100644 docs/tutorials/create-dapp.md diff --git a/docs/tutorials/create-dapp.md b/docs/tutorials/create-dapp.md new file mode 100644 index 00000000..df67ebe5 --- /dev/null +++ b/docs/tutorials/create-dapp.md @@ -0,0 +1,424 @@ +--- +title: Create dApp in React +id: create-dapp +slug: /create-dapp +--- + +import Tabs from '@theme/Tabs' +import TabItem from '@theme/TabItem' + +In this tutorial we will go over creating dApp in React with the `bee-js` library. Once build this dApp can be hosted directly on the Swarm network and interact with it. + +## Creating the dApp boilerplate + +We will use React Create App to bootstrap the environment for us. Run the following command (you can replace the `dApp` with your own project name). + + + + +```sh +npx create-react-app dApp +``` + + + + +```sh +npm init react-app dApp +``` + + + + +```sh +yarn create react-app dApp +``` + + + + +For typescript support don't forget to add the `--template typescript` option: + + + + +```sh +npx create-react-app dApp --template typescript +``` + + + + +```sh +npm init react-app dApp --template typescript +``` + + + + +```sh +yarn create react-app dApp --template typescript +``` + + + + +## Adding bee-js + +First of all, we need to add `bee-js` as a dependency to the project. Navigate to the project directory (e.g. in our case `cd dApp`) and let's install `bee-js`: + + + + +```sh +npm install @ethersphere/bee-js --save +``` + + + + +```sh +yarn add @ethersphere/bee-js --save +``` + + + + +Now let's edit the main App file. + + + + +`./src/App.tsx` +```ts +import React, { useState } from 'react' +import './App.css' +import { Bee } from '@ethersphere/bee-js' + +const beeUrl = "https://gateway.ethswarm.org" +const bee = new Bee(beeUrl) + +function App() { + const [ file, setFile ] = useState(null) + const [ link, setLink ] = useState(null) + const [ uploading, setUploading ] = useState(false) + + const handleSubmit = async (event: React.FormEvent)=> { + event.preventDefault() + + if (file) { + setUploading(true) + const hash = await bee.uploadFile(file) + setLink(`${beeUrl}/files/${hash}`) + setUploading(false) + } + } + + const onFileChange = (e: React.ChangeEvent) => { + const f = e.target && e.target.files && e.target.files[0] + + setFile(f) + } + + return ( +
+

Upload file to Swarm

+
+ + +
+ { uploading && Uploading... } + { link && {link} } +
+ ) +} + +export default App +``` + +
+ + +`./src/App.jsx` +```js +import React, { useState } from 'react' +import './App.css' +import { Bee } from '@ethersphere/bee-js' + +const beeUrl = "https://gateway.ethswarm.org" +const bee = new Bee(beeUrl) + +function App() { + const [ file, setFile ] = useState(null) + const [ link, setLink ] = useState(null) + const [ uploading, setUploading ] = useState(false) + + const handleSubmit = async (event)=> { + event.preventDefault() + + if (file) { + setUploading(true) + const hash = await bee.uploadFile(file) + setLink(`${beeUrl}/files/${hash}`) + setUploading(false) + } + } + + const onFileChange = (e) => { + const f = e.target && e.target.files && e.target.files[0] + + setFile(f) + } + + return ( +
+

Upload file to Swarm

+
+ + +
+ { uploading && Uploading... } + { link && {link} } +
+ ) +} + +export default App +``` + +
+
+ +Let's break it down, the first important lines are importing the `Bee` class and creating the bee instance: + + + + +```ts +import { Bee } from '@ethersphere/bee-js' + +const beeUrl = "https://gateway.ethswarm.org" +const bee = new Bee(beeUrl) +``` + + + + +```js +import { Bee } from '@ethersphere/bee-js' + +const beeUrl = "https://gateway.ethswarm.org" +const bee = new Bee(beeUrl) +``` + + + + +Next we'll have a look at the content of the `App` function. At the start of the function, we create few state variables. The `file` will hold the file to be uploaded, the `link` eventually contains the URL to download the file once it is uploaded to Swarm, and the `uploading` value indicates if the file is being uploaded right now. + +At the bottom of the `App` function there is a JSX code with a header, simple form to upload a single file and two text fields that are conditionally displayed. The important thing to notice is the `onFileChange` handler on the file input and the `handleSubmit` function. + + + + +```ts +function App() { + const [ file, setFile ] = useState(null) + const [ link, setLink ] = useState(null) + const [ uploading, setUploading ] = useState(false) + + // Omitted code... + + return ( +
+

Upload file to Swarm

+
+ + +
+ { uploading && Uploading... } + { link && {link} } +
+ ) +} +``` + +
+ + +```js +function App() { + const [ file, setFile ] = useState(null) + const [ link, setLink ] = useState(null) + const [ uploading, setUploading ] = useState(false) + + // Omitted code... + + return ( +
+

Upload file to Swarm

+
+ + +
+ { uploading && Uploading... } + { link && {link} } +
+ ) +} +``` + +
+
+ +Lets disect the two handlers. The `onFileChange` function listens to the file input changes and when a new file is selected, it just stores it in the `file` state variable. + + + + +```ts +const onFileChange = (e: React.ChangeEvent) => { + const f = e.target && e.target.files && e.target.files[0] + + setFile(f) +} +``` + + + + +```js +const onFileChange = (e) => { + const f = e.target && e.target.files && e.target.files[0] + + setFile(f) +} +``` + + + + + +The `handleSubmit` function does all the interesting work. If a file is selected, it uploads it to Swarm using the `uploadFile` function which returns the hash of the file. The function then sets the download URL and marks the upload process done. + + + + +```ts + const handleSubmit = async (event: React.FormEvent)=> { + event.preventDefault() + + if (file) { + setUploading(true) + const hash = await bee.uploadFile(file) + setLink(`${beeUrl}/files/${hash}`) + setUploading(false) + } + } +``` + + + + +```js + const handleSubmit = async (event)=> { + event.preventDefault() + + if (file) { + setUploading(true) + const hash = await bee.uploadFile(file) + setLink(`${beeUrl}/files/${hash}`) + setUploading(false) + } + } +``` + + + + +## Making it a dApp - uploading to Swarm + +For the project to trully be a dApp, it should not be hosted on any centralised system. One way to achieve that is to upload it to Swarm. Before we do so, we need to edit few more things and build the project. + +Let's start with the `package.json` file. Here we need to set the homepage. This line makes the build process use relative path in the resulting bundle. + +``` + "homepage": ".", +``` + +Next, we need to build the project with the provided build command. + + + + +```sh +npm run build +``` + + + + +```sh +yarn build +``` + + + + +This will create a `dist` folder that should be uploaded to the Swarm. We are working on `swarm-cli` which will make the upload process easier, but in the mean time you can follow the [Host Your Website on Swarm tutorial in the bee docs](https://docs.ethswarm.org/docs/getting-started/host-your-website-using-ens). \ No newline at end of file diff --git a/sidebars.js b/sidebars.js index 6602c29e..ef14e331 100644 --- a/sidebars.js +++ b/sidebars.js @@ -12,6 +12,14 @@ module.exports = { ], collapsed: false }, + { + type: 'category', + label: 'Tutorials', + items: [ + 'tutorials/create-dapp', + ], + collapsed: false + }, { type: 'category', label: 'API Reference', From 1256f5e4aa8dcbd077ec1742b5f51dda386f28b3 Mon Sep 17 00:00:00 2001 From: Vojtech Simetka Date: Wed, 17 Feb 2021 19:38:14 +0100 Subject: [PATCH 2/2] chore: moved the filenames to the code block title --- docs/tutorials/create-dapp.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/tutorials/create-dapp.md b/docs/tutorials/create-dapp.md index df67ebe5..893ae662 100644 --- a/docs/tutorials/create-dapp.md +++ b/docs/tutorials/create-dapp.md @@ -115,8 +115,7 @@ Now let's edit the main App file. ]}> -`./src/App.tsx` -```ts +```ts title="src/App.tsx" import React, { useState } from 'react' import './App.css' import { Bee } from '@ethersphere/bee-js' @@ -165,8 +164,7 @@ export default App -`./src/App.jsx` -```js +```js title="src/App.jsx" import React, { useState } from 'react' import './App.css' import { Bee } from '@ethersphere/bee-js'