# Building a To-Do List React App with Dgraph - Dgraph Blog

**URL:** <https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355>\
**Category:** Blog\
**Created:** [April 18, 2019, 9:03pm UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355 "2019-04-18T21:03:24Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![mrjn](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/mrjn/32/775_2.png) [@mrjn](https://discuss.dgraph.io/u/mrjn)\
**Post date:** [April 18, 2019, 9:03pm UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/1 "2019-04-18T21:03:25Z")

</div>

Before We Begin 

In this tutorial we will build a To-Do List application using [React](https://reactjs.org/) JavaScript library and Dgraph as a backend database. We will use [dgraph-js-http](https://github.com/dgraph-io/dgraph-js-http) to greatly simplify the life of JavaScript developers when accessing Dgraph databases.

The tutorial is split into several steps:

1. [Creating a React App](https://blog.dgraph.io%23ref-creating-app)

2. [Starting a local Dgraph server using docker-compose](https://blog.dgraph.io%23ref-docker-compose)

3. [Connecting to Dgraph from JavaScript and fetching data](https://blog.dgraph.io%23ref-fetch-data)

4. [Storing data in Dgraph](https://blog.dgraph.io%23ref-write-data)

If you are already familiar with setting up a React application and want to skip straight to the Dgraph-specific part of the tutorial, you can start from [Section 2](https://blog.dgraph.io%23ref-docker-compose).

### 1. Creating a React App

Nowadays it’s pretty simple to get started with React, thanks to the awesome `create-react-app` script. Let’s run it:

```
  npx create-react-app dgraph-react-todomvc

```

(`npx` command is part a of the standard [Node.js installation](https://nodejs.org/en/download/).)

[](https://blog.dgraph.io/images/react-todomvc/create-react-app.svg)

 Verifying the new app 

Let’s compile and test our application. Like most tasks with `create-react-app` we need only one command to run the development server and it will even open a browser window for us:

```
  yarn start

```

![](upload://jDubfNgYPKZzbdL8LwNgxl59X0J.jpeg)

Once we’ve made sure everything is working as expected it’s a good time to save our progress so far to a version control system. At Dgraph we’re using [GitHub](https://github.com/) so I will just commit everything with Git:

```
 git commit -am 'Output of the create-react-app'

```

And since I’ve created a public repository, you can [view and clone](https://github.com/dgraph-io/dgraph-react-todomvc/commits/master) all steps of this tutorial at any time. (I won’t digress on how I did this, as it goes beyond the scope of this tutorial.)

 Adding custom code 

So far we’ve been generating boilerplate code not specific to the to-do application we’re building. It’s time to make our app more unique, but as the first step, let’s just delete all the styling we’re not going to need.

As this is not a very creative process (quite the opposite of creative, actually) I won’t go into details. You can [view](https://github.com/dgraph-io/dgraph-react-todomvc/commit/a18d1fd958ccc3c8d38940478746cf22c83c772f) the changed files on GitHub.

 Connecting TodoMVC styles 

Since I’m not a designer, but still like my apps to look pretty, I’m going to use high quality off-the-shelf [CSS styles](https://github.com/tastejs/todomvc-app-css), released by the [TodoMVC team](http://todomvc.com/).

Adding those to the project is as easy as

```
 yarn add todomvc-app-css

```

We also need to load the new styles onto the page, by importing them in the `App.js`:

```
  import 'todomvc-app-css/index.css'

```

And after these two changes we can write some HTML to use the styles. Let’s update our main `render()` method to do just that (also in the `App.js`):

```
  ...
  render() {
    return (
      <div>
        <header className="header">
          <h1>todos</h1>
          <input
            className="new-todo"
            placeholder="What needs to be done?"
            autoFocus={true}
          />
        </header>
      </div>
    )
  }
  ...

```

Now, since we still have our dev server running in the background (the one we started with `yarn start`), our app will get live reloaded and start to look pretty fancy:

![](upload://ixKjtUEqZX7z68nlaJKylSCghYg.jpeg)

Sadly it isn’t doing anything useful but we’ll get to that in a minute.

I’ve also made small tweaks to the `index.html` but those are fairly self-explanatory, and can be seen in the [git history](https://github.com/dgraph-io/dgraph-react-todomvc/commit/1fbbda8263cb6c7ca0a6c910619080d50a5c2340#diff-528c3923d718a8860f5d8c05c3931c55).

 Adding React Components 

There’s just one more step before we get to the juicy bit - using Dgraph. Trust me, I want to start telling you about it ASAP.

So, without further ado, let’s get our frontend code done with by copying the ready made React components from the [TodoMVC React Example](https://github.com/tastejs/todomvc/tree/gh-pages/examples/react).

The [files I’ve added](https://github.com/dgraph-io/dgraph-react-todomvc/commit/68a12fbb484db71c1ef988e16ba2febf39ea27a3) are somewhat different to the “official” TodoMVC React code because I’ve modified the source to use all the shiny new features of modern JavaScript, Babel and Webpack: classes, modules, lambda functions, let/const keywords etc.

It’s another hairy but straightforward refactoring, so let’s not spend too much time on it.

After the dust settled our app can respond to the user input, show and store some to-dos:

![](upload://7ojivYtliLClxdykZIMjyvQ6bYU.jpeg)

### 2. Starting a local Dgraph server

There are many ways to [install and run Dgraph](https://docs.dgraph.io/get-started/) depending on your machine setup. I personally prefer to use [`docker-compose`](https://docs.docker.com/compose/gettingstarted/) as it keeps all of the configuration in one file.

First, let’s create a `docker-compose.yml` configuration file. It’s up to you where you want to keep it, for our project the folder `dgraph-react-todomvc/dgraph/` seems logical.

```
version: "3.2"
services:
  zero:
    image: dgraph/dgraph:v1.0.13
    volumes:
      - type: volume
        source: dgraph
        target: /dgraph
        volume:
          nocopy: true
    ports:
      - 5080:5080
      - 6080:6080
    restart: on-failure
    command: dgraph zero --my=zero:5080
  server:
    image: dgraph/dgraph:v1.0.13
    volumes:
      - type: volume
        source: dgraph
        target: /dgraph
        volume:
          nocopy: true
    ports:
      - 8080:8080
      - 9080:9080
    restart: on-failure
    command: dgraph alpha --my=server:7080 --lru_mb=2048 --zero=zero:5080
  ratel:
    image: dgraph/dgraph:v1.0.13
    volumes:
      - type: volume
        source: dgraph
        target: /dgraph
        volume:
          nocopy: true
    ports:
      - 8000:8000
    command: dgraph-ratel
volumes:
  dgraph:

```

Then we can fire up all three processes (Dgraph Alpha, Zero and Ratel) with one simple command:

```
  docker-compose up

```

I usually run it in a separate terminal so I can check the server output at any time or shutdown everything by pressing `Ctrl+C`.

The output of `docker-compose` will be a bit noisy, but should look something like this:

[](https://blog.dgraph.io/images/react-todomvc/docker-compose-up.svg)

 Viewing database with Ratel 

It sure looks like it’s doing something how do we know if it works as expected? Let’s fire up a web browser and give Ratel a try — Dgraph’s web UI.

Opening [http://localhost:8000](http://localhost:8000) should take you to the Ratel loading screen.

From there you can click on [🚀 Launch Latest](http://localhost:8000/?latest) to load the latest stable version of Ratel and run some queries:

![](upload://5tkq0JHJjPLL9nD111OyUXNKDF2.gif)

### 3. Connecting to Dgraph from JavaScript and fetching data

Dgraph team has built [client libraries](https://docs.dgraph.io/clients/) for various languages. Since we are building a web app without a backend server, and JavaScript in the browser is very restricted in what it is allowed to do, we will be using [dgraph-js-http](https://github.com/dgraph-io/dgraph-js-http).

You may have noticed there’s also [dgraph-js](https://github.com/dgraph-io/dgraph-js) available via `npm`.

The main difference between the two is `dgraph-js-http` communicates with Dgraph via HTTP queries and `dgraph-js` uses network sockets and [gRPC](https://grpc.io/). gRPC is more efficient, but currently there’s no network sockets API available to webpages. Therefore `dgraph-js-http` is our only option. For many use cases, the difference in performance is negligible so let’s start building our application around the HTTP protocol.

 Installing dgraph-js-http 

As with any other npm package, adding `dgraph-js-http` to our project is super simple:

```
  yarn install dgraph-js-http

```

And after yarn has downloaded the latest version of the package, we can import it in our `TodoModel.js`:

```
import * as dgraph from 'dgraph-js-http'

```

In order to communicate with Dgraph we need to create an instance of the `DgraphClient`. Let’s do it inside our `TodoModel` constructor:

```
  const clientStub = new dgraph.DgraphClientStub("http://localhost:8080")
  this.dgraph = new dgraph.DgraphClient(clientStub)

```

With a client object ready we can fetch to-dos using a [GraphQL+- query](https://docs.dgraph.io/query-language/):

```
  async fetchTodos() {
    const query = `{
      todos(func: has(is_todo))
      {
        uid
        title
        completed
      }
    }`
    const res = await this.dgraph.newTxn().query(query)
    return res.data.todos || []
  }

```

We also need to call `fetchTodos()` when our web app is loaded, store its result inside the model, and also get rid of the no-longer-needed localStorage code.

For the former task I’ve created a helper method `fetchAndInform()`:

```
  async fetchAndInform() {
    this.todos = await this.fetchTodos()
    this.inform()
  }

```

And placed it as the last call in the `TodoModel` constructor:

```
  constructor() {
    const clientStub = new dgraph.DgraphClientStub("http://localhost:8080")
    this.dgraph = new dgraph.DgraphClient(clientStub)
    this.todos = []
    this.fetchAndInform()
  }

```

As the final touch, we can stop manually generating unique `id`s and start using much more compact and efficient Dgraph’s `uid` field:

![](upload://xkIwzu7ei2q6pUluYS4wde30gcg.svg)

All the major changes I’ve outlined above and some minor cleanups I’ve omitted are available in this [GitHub commit](https://github.com/dgraph-io/dgraph-react-todomvc/commit/042ee296283f10994fa35e2ba6e0e6b98a06168d).

 Adding test data to Dgraph 

So we’ve written a bit of code, removed a bit more, but how do we know if it’s actually working as expected?

If we simply reload the web app we will see an empty to-do list. Any items we add via the UI disappear on browser refresh.

That is happening because our Dgraph database is empty at the moment and we haven’t coded our components to populate it yet.

Every time the page is refreshed our query returns an empty set of to-dos, and that is what we see on the webpage.

Since we have the Ratel UI (we [have already played with it](https://blog.dgraph.io%23ref-test-ratel)) we can easily add some test data.

Let’s open our local Ratel instance ([http://localhost:8000/?latest](http://localhost:8000/?latest)) and execute the following mutation:

```
{
  "set": [
    {
      "uid": "_:todo1",
      "is_todo": "true",
      "title": "First Todo",
      "completed": "false"
    },
    {
      "uid": "_:todo2",
      "is_todo": "true",
      "title": "Second Todo",
      "completed": "true"
    }
  ]
}

```

In Ratel the successful response should look like this:

![](upload://al3o3ZSq3Wl3AsvBfyHeC6kLuhU.jpeg)

Note that we needed to click the “Mutate” radio button.

Ratel also lets us test the query our application is sending:

![](upload://u8gMxHunoGrafN8MziBEFGSrApm.jpeg)

Now, after we made sure we have the right data in the database, let’s see if our application is accessing it correctly:

![](upload://opeTyVcE5M9JFe2yTrt69QTbFRz.jpeg)

This is almost perfect, except our mutation said only the second to-do was completed, but the first was not. Why did this happen?

If you take a closer look at the Ratel query [screenshot](https://blog.dgraph.io%23ref-img-ratel-query) above, you will notice that `completed` is returned as a JSON string, not a boolean:

```
  ...
      {
        "uid": "0x3",
        "title": "First Todo",
        "completed": "false"
      },
  ...

```

That second pair of double quotes does matter in the line `"completed": "false"`. We have not yet told Dgraph to parse the values of `completed` as booleans, so Dgraph is storing and returning them as strings. To change that we will need to adjust Schema.

 Modifying Schema with Ratel 

As we have determined, we need to tell Dgraph to convert the `completed` predicate from string to boolean.

Ratel has full support for managing Dgraph schemas, so such changes takes only a handful of clicks:

![](upload://nMnCLsZoB4yzBtQVoLVSQzALmNc.jpeg)

After we’ve modified the schema Dgraph takes care of the rest — it will migrate existing data to the new type and will start responding to new queries with values coerced to the right data type.

We can verify that this is actually happening by re-running the query in Ratel, or by refreshing our TodoMVC app:

### 4. Storing data in Dgraph

We have learned how to query Dgraph for data and show results to the user. The only missing piece of the puzzle is writing our to-dos to Dgraph so they don’t get lost every time our users close a browser tab.

Let’s start by sending newly created to-dos to Dgraph, and then we’ll write code for updating or deleting the existing ones.

 Creating new to-do items in Dgraph 

We represent to-do items as graph nodes. To create a new node we’ll need a transaction, and a mutation:

```
  async addTodo(title) {
    try {
      const res = await this.dgraph.newTxn().mutate({
        setJson: {
          uid: "_:newTodo",
          is_todo: true,
          title,
          completed: false,
        },
        commitNow: true,
      })
      console.info('Created new to-do with uid', res.data.uids.newTodo)
    } catch (error) {
      alert('Database write failed!')
      console.error('Network error', error)
    } finally {
      this.fetchAndInform()
    }
  }

```

`commitNow` informs Dgraph that this transaction will not modify any more data and should be committed right away.

In a more complex application we could set it to `false` (or omit it altogether) if we planned to perform more reads or mutations. In that case we’d have to manually call [`commit()`](https://github.com/dgraph-io/dgraph-js-http#commit-a-transaction) at the right moment.

Note how the response object contains the `uid` of the newly created item. Since we used the alias `"_:newTodo"` in our `setJson` mutation, the uid of that node is stored in the `uids.newTodo` of the response data.

Our application can now write data to Dgraph, and we can see auto-incremented `uid` values printed to console:

![](upload://aOEG4eMvJ3LY4U0ntZ8mBANBCx4.jpeg)

You can also go to Ratel and re-run our query — the new to-dos will appear in the response.

 Deleting nodes from Dgraph 

Code to delete a to-do is very similar to that for creating a to-do. We only need to specify a `uid` of the node being deleted, and use the `deleteJson` field on the mutation object:

```
  async destroy(todo) {
    try {
      await this.dgraph.newTxn().mutate({
        deleteJson: {
          uid: todo.uid
        },
        commitNow: true,
      })
    } catch (error) {
      alert('Database write failed!')
      console.error('Network error', error)
    } finally {
      this.fetchAndInform()
    }
  }

```

Deleting multiple to-dos for the `clearCompleted()` method can be done by passing an array in the `deleteJson`:

```
    ...
    const uidsToDelete = this.todos
        .filter(({ completed }) => completed)
        .map(({ uid }) => ({ uid }))
    await this.dgraph.newTxn().mutate({
      deleteJson: uidsToDelete,
      commitNow: true,
    })
    ...

```

 Updating data in Dgraph 

Our application can create new to-dos in the database, can read the data back, and can remove unnecessary data.

We just need to enable our users to edit their existing to-dos and we’re done!

As you may have guessed already, editing a node property is just another transaction:

```
  async save(todoToSave, newTitle) {
    try {
      await this.dgraph.newTxn().mutate({
        setJson: {
          uid: todoToSave.uid,
          title: newTitle,
        },
        commitNow: true,
      })
    } catch (error) {
      console.error('Network error', error)
    } finally {
      this.fetchAndInform()
    }
  }

```

We don’t need to pass the entire object back to Dgraph. We only include the new value for `title` in our mutation. Other predicates (such as `completed`) will have their values preserved.

Methods that change completion status, `toggle(...)` and `toggleAll(...)`, also need to be rewritten to use Dgraph transactions, but this exercise is [left to the reader ;)](https://github.com/dgraph-io/dgraph-react-todomvc/commit/876b5af1e99308c42bbcb72ffe3082dbbd6e5914).

Here’s the final product:

### Summary

We have built a web app that is capable of accessing Dgraph to store and display data. To do that we have learned how to run Dgraph inside Docker containers, adjusted schema in Ratel, and learned how to send GraphQL+- queries to read data and to commit transactions in order to insert or modify data in Dgraph.

There are many more things a developer of a real-life application would need to implement. Most notably I’ve omitted access control and backups, among other things. However, I hope this tutorial gave you an interesting and useful starting point for creating your own Dgraph-powered applications.

* * *
This is a companion discussion topic for the original entry at [https://blog.dgraph.io/post/building-todo-list-react-dgraph/](https://blog.dgraph.io/post/building-todo-list-react-dgraph/)

---

<div class="post-metadata">

**Author:** ![cocodrino](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/cocodrino/32/1236_2.png) [@cocodrino](https://discuss.dgraph.io/u/cocodrino)\
**Post date:** [May 6, 2019, 3:40pm UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/2 "2019-05-06T15:40:30Z")

</div>

nice article, I hope a future post about some integration with nodejs or go graphql server ;D

---

<div class="post-metadata">

**Author:** ![cje](https://avatars.discourse-cdn.com/v4/letter/c/edb3f5/32.png) [@cje](https://discuss.dgraph.io/u/cje)\
**Post date:** [November 23, 2019, 5:09am UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/3 "2019-11-23T05:09:29Z")

</div>

Nice Article - any chance of a similar example using Angular 8? We are currently using Angular 8 with the ApolloAngular client with a node.js graphQL server over a postgresDB. I like what you are doing with Dgraph and would appreciate any examples that would assist migrating from a graphQL/postgresDB backend to Dgraph.

---

<div class="post-metadata">

**Author:** ![Shekar](https://avatars.discourse-cdn.com/v4/letter/s/eb8c5e/32.png) [@Shekar](https://discuss.dgraph.io/u/Shekar)\
**Post date:** [November 23, 2019, 11:10am UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/4 "2019-11-23T11:10:14Z")

</div>

Thank you for the question. I will have our engineering team look at your question and respond promptly.

---

<div class="post-metadata">

**Author:** ![paulftw](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/paulftw/32/1569_2.png) [@paulftw](https://discuss.dgraph.io/u/paulftw)\
**Post date:** [December 27, 2019, 12:24pm UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/5 "2019-12-27T12:24:01Z")

</div>

Porting this example to Angular would mean simply creating an instance of [TodoModel](https://github.com/dgraph-io/dgraph-react-todomvc/blob/master/src/TodoModel.js) and subscribing to its updates / using its methods to write to the database.

---

<div class="post-metadata">

**Author:** ![BaoNguyen1507](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/baonguyen1507/32/3723_2.png) [@BaoNguyen1507](https://discuss.dgraph.io/u/BaoNguyen1507)\
**Post date:** [July 6, 2020, 2:51am UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/6 "2020-07-06T02:51:53Z")

</div>

Access to fetch at ‘[http://localhost:8080/commit?startTs=0&abort=true](http://localhost:8080/commit?startTs=0&abort=true)’ from origin ‘[http://localhost:3000](http://localhost:3000)’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.  
Hi there, I have faced this issue when I try to use add new todo item. Please help me! Many thanks.

---

<div class="post-metadata">

**Author:** ![amaster507](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/amaster507/32/4123_2.png) [@amaster507](https://discuss.dgraph.io/u/amaster507)\
**Post date:** [July 6, 2020, 4:28am UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/7 "2020-07-06T04:28:07Z")

</div>

Welcome to Dgraph!

If you are just getting started I would look at using the graphql endpoint. There are some caveats but it is faster IMO to get up and running even faster. Slash makes it even better by making is a fully managed SaaS.

[https://graphql.dgraph.io/todo-app-tutorial/](https://graphql.dgraph.io/todo-app-tutorial/)

I know what CORS is and how to handle it on an endpoint by fixing headers manually, but don’t know how Dgraph handles that, so I can’t answer your main question, but maybe this can alleviate your problems.

If you have questions for how the graphql endpoint varies from the Dgraph regular endpoint let me know as that is something I struggled with too getting started.

---

<div class="post-metadata">

**Author:** ![catherineluse](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/catherineluse/32/4329_2.png) [@catherineluse](https://discuss.dgraph.io/u/catherineluse)\
**Post date:** [August 28, 2020, 2:59am UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/8 "2020-08-28T02:59:29Z")

</div>

How do you add types or schema to this project?

Based on reading the [documentation](https://dgraph.io/docs/graphql/todo-app-tutorial/todo-schema-design/) I tried to use this command to add a couple of basic types to the Dgraph server that was created with the docker-compose.yml:

```auto
$ curl -X POST localhost:8080/admin/schema --data-binary '@schema.graphql'

```

But it didn’t update the schema, it only said this:

```auto
Dgraph browser is available for running separately using the dgraph-ratel binary

```

When the database is set up in a single Docker container, that command yields this:

```auto
{"data":{"code":"Success","message":"Done"}}

```

So my question is, how would you modify the schema for Dgraph if the database is set up like it is in the linked tutorial using the docker-compose.yml?

I also had the same problem as [BaoNguyen1507](http://discuss.hypermode.com/u/BaoNguyen1507)

---

<div class="post-metadata">

**Author:** ![aman-bansal](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/aman-bansal/32/4475_2.png) [@aman-bansal](https://discuss.dgraph.io/u/aman-bansal)\
**Post date:** [August 28, 2020, 9:19am UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/9 "2020-08-28T09:19:14Z")

</div>

Hi @catherineluse  
Please try with the latest docker image. We have come a long way since this tutorial was setup. You can find the latest docker-compose file [here](https://raw.githubusercontent.com/dgraph-io/dgraph/master/contrib/config/docker/docker-compose.yml).

One thing to note is that you might run into whitelist issue. You should be able to fix that by changing alpha start command to `dgraph alpha --my=alpha:7080 --lru_mb=2048 --zero=zero:5080 --whitelist 0.0.0.0/0` for dev environment. I request you to go through this [documentation](https://dgraph.io/docs/deploy/dgraph-administration/#whitelisting-admin-operations).

> [@catherineluse](#):
>
> I also had the same problem as [BaoNguyen1507](http://discuss.hypermode.com/u/BaoNguyen1507)

If it’s the CORS issue can you please try with enabling CORS via plugin/extensions available for major browsers(one such available extension for google chrome can be found [here](https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf/related?hl=en) ).

You can use this [link](https://webbrowsertools.com/test-cors/) to check your browsers CORS policy

---

<div class="post-metadata">

**Author:** ![catherineluse](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/catherineluse/32/4329_2.png) [@catherineluse](https://discuss.dgraph.io/u/catherineluse)\
**Post date:** [September 9, 2020, 3:40am UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/10 "2020-09-09T03:40:58Z")

</div>

It worked after I upgraded dgraph-js-http to version 20.07.0.

---

<div class="post-metadata">

**Author:** ![immersinn](https://avatars.discourse-cdn.com/v4/letter/i/85f322/32.png) [@immersinn](https://discuss.dgraph.io/u/immersinn)\
**Post date:** [May 9, 2021, 10:23pm UTC](https://discuss.dgraph.io/t/building-a-to-do-list-react-app-with-dgraph-dgraph-blog/4355/12 "2021-05-09T22:23:22Z")

</div>

using “dgraph-js-http”: “^21.3.0”

also updated docker-compose for LOCAL usage / playground. Note this allows all IPs access to alpha (e.g. for updating schema as discussed in tutorial). Wouldn’t use this in any “real” config / setup.

May get a ratel login screen, but as long as you have 3 greens, you can just hit continue.

```auto
version: "3.2"
services:
  zero:
    image: dgraph/dgraph:v20.11.3
    volumes:
      - type: volume
        source: dgraph
        target: /dgraph
        volume:
          nocopy: true
    ports:
      - 5080:5080
      - 6080:6080
    restart: on-failure
    command: dgraph zero --my=zero:5080
  alpha:
    image: dgraph/dgraph:v20.11.3
    volumes:
      - type: volume
        source: dgraph
        target: /dgraph
        volume:
          nocopy: true
    ports:
      - 8080:8080
      - 9080:9080
    restart: on-failure
    command: dgraph alpha --my=alpha:7080 --lru_mb=2048 --zero=zero:5080 --whitelist=0.0.0.0/0
  ratel:
    image: dgraph/dgraph:v20.11.3
    ports:
      - 8000:8000
    command: dgraph-ratel

volumes:
  dgraph:

```
