Version #2: ability to add a new item to the list and save it in the database

At this point, you shall be able to see a fetched list in a specified order. Let's make an ability to add a new item to the end of the list.

This version contains many updated code. Let's split it on two steps.

Version #2.1: fetched list items

Here we prepare currentListId property, where we will keep the ID of the list. It is required, because each logged user of the application, will have his own list (with different dashboardItems)

NOTE: Below, we introduce a currentListId: null property.
In future, production application the list will be created on the backend before fetch request.
Below's implementation approach is just for beginners.
If you have any questions, regarding that implementation please request support at our ReactJS.co facebook community page https://www.facebook.com/groups/reactjs.co/.

OK, let's start our work so you will get even better all the 4 points above in practise.

1) First of all, we need to create a new property in our dashboard's reducer object. We will call it currentListId and it will store the ID from the databse, of our list called dashboardMainListOrder:

graphql apollo tutorial

2) The most important part is to define the const currentListId (line 113).

graphql apollo tutorial

Important: we updated a promise answer (was an array and now is object). You should be carefully, cause catch method also should be updated. That meant dispatch(fetchDashboardDataSuccess(dashboardItemsArray)) line 151 will invoked with object.

3) And the last one is improve our reducer (FETCH_DASHBOARD_DATA_SUCCESS action handler). It will save also the list's ID in our reducer.

graphql apollo tutorial


The commit from the above sub-chapter:
https://github.com/ReactPoland/reactjs-redux-tutorial/commit/graph-chapter-4-a

Version #2.2: Create and save item

Plan for making the adding ability feature work is as following:

  • 1) Add a new function called dashboardAddItemAsync in the src/routes/Dashboard/modules/dashboard.js
  • 2) Improve the DASHBOARD_ADD_ITEM action handler altogether with the dispatching it correctly via the dispatch(dashboardAddItem({ newDashboardItemValue, newDashboardItemID }))
  • 3) Improve the src/routes/Dashboard/containers/DashboardContainer.js codebase, so we will introduce a new function called "dashboardAddItemAsync". This function is making an async request to the GraphQL's server

1) Here we start working on the next function called dashboardAddItemAsync. First three steps (1-4) are adding the item into the DashboardItem class, the 4th step is just console logging the ID from the database:
graphql apollo tutorial


In the steps 5 to 8, we are editing (update's mutation query) the list with use of orderListIdsArray from the scaphold's GraphQL DashboardItemListOrder class:
graphql apollo tutorial

Below is the complete dashboardAddItemAsync function from the src/routes/Dashboard/modules/dashboard.js (screenshots from diffs of the same function are above in the point 4 and 5):


export const dashboardAddItemAsync = ({ label }) => {
  return async (dispatch, getState) => {
    const { currentListId, dashboardItems } = getState().dashboard

    // *****************************************************************
    // *************
    // ************* STEP #1 - (preparation of the mutation query)
    // *************
    const mutationInsert = gql`mutation CreateNested($data: CreateDashboardItemInput!) {
      createDashboardItem(input: $data) {
        changedDashboardItem {
          id
          label
        }
      }
    }`

    // *****************************************************************
    // *************
    // ************* STEP #2. - preparation of the variables that we need to insert
    // *************
    const variablesInsert = {
      data: { label }
    }

    // *****************************************************************
    // *************
    // ************* STEP #3. - making the mutations and retrieving the newDashboardItemID
    // *************

    try {
      const newDashboardItem = await client
        .mutate({ mutation: mutationInsert, variables: variablesInsert })
        .then((results) => results.data.createDashboardItem.changedDashboardItem)

      // *****************************************************************
      // *************
      // ************* STEP #4. - OK, we've got the ID. Let's update the list
      // *************
      console.info('here is the ID: ', newDashboardItem.id)

      // *****************************************************************
      // *************
      // ************* STEP #5. - preparation of the mutation query
      // *************
      const mutationListUpdate = gql`mutation UpdateDashboardItemListOrder($data: UpdateDashboardItemListOrderInput!) {
        updateDashboardItemListOrder(input: $data) {
          changedDashboardItemListOrder {
            id
            orderListIdsArray
          }
        }
      }`

      // the currentListArray holds an array of IDs, which we will update later
      // via the GraphQL query (see step 6, below)
      const currentListArray = dashboardItems.map((dashboardItem) => dashboardItem.id)

      // *****************************************************************
      // *************
      // ************* STEP #6. - preparation of the variables that we need to have in order to update
      // *************
      const variablesListUpdate = {
        data: {
          // this ID, is the ID of the list which we want to update
          id: currentListId,
          // here is going a current list with all IDS (including the new one)
          // we are using the ES6's "..."  spread operator
          orderListIdsArray: [...currentListArray, newDashboardItem.id]
        }
      }

      // *****************************************************************
      // *************
      // ************* STEP #7. - doing the async backend call with all details
      // ************* (GraphQL query doing the heavy lifting now)
      // *************
      await client
        .mutate({ mutation: mutationListUpdate, variables: variablesListUpdate })

      // *****************************************************************
      // *************
      // ************* STEP #8. - we have updated the list, let's dispatch the new value and ID
      // *************
      dispatch(dashboardAddItem(newDashboardItem))
    } catch (errorReason) {
      // Here you handle any errors.
      // You can dispatch some
      // custom error actions like:
      // dispatch(yourCustomErrorAction(errorReason))

      alert('Apollo client add handler error. See console')
      console.error('apollo client add handler error:', errorReason.message)
    }
  }
}

2) Next we are improving the DASHBOARD_ADD_ITEM action handler, so instead of mocked ID it will use a real ID from our database:
graphql apollo tutorial


3) The last step is to edit container src/routes/Dashboard/containers/DashboardContainer.js and view src/routes/Dashboard/components/Dashboard.js.

So wer will use there the this.props.dashboardAddItemAsync({ newDashboardItemValue: val, dashboardState: this.props.dashboard }) instead of the old one (dashboardAddItem) function:

graphql apollo tutorial

At this point, you will be able to see the following:

ANIMATED-GIF-TO-ADD


The commit from the above sub-chapter:
https://github.com/ReactPoland/reactjs-redux-tutorial/commit/graph-chapter-4-b

React Poland 2017