{"size": 7627, "ext": "js", "max_stars_repo_path": "src/pages/quickstart/websockets/step-2.js", "max_stars_repo_name": "SeongJinAhn/dbserver", "max_stars_repo_stars_event_min_datetime": "2016-09-25T01:03:47.000Z", "max_stars_repo_stars_event_max_datetime": "2020-06-03T23:02:03.000Z", "max_issues_repo_path": "src/pages/quickstart/websockets/step-2.js", "max_issues_repo_name": "lore/www.lorejs.org", "max_issues_repo_issues_event_min_datetime": "2016-11-22T18:25:06.000Z", "max_issues_repo_issues_event_max_datetime": "2022-01-15T01:11:47.000Z", "max_forks_repo_path": "src/pages/quickstart/websockets/step-2.js", "max_forks_repo_name": "SeongJinAhn/dbserver", "max_forks_repo_forks_event_min_datetime": "2016-11-22T18:10:06.000Z", "max_forks_repo_forks_event_max_datetime": "2018-07-10T08:45:01.000Z"}
{"max_stars_count": 2, "max_issues_count": 23, "max_forks_count": 10, "avg_line_length": 31.9121338912, "max_line_length": 118, "alphanum_fraction": 0.5754556182}
import React from 'react';
import Link from 'gatsby-link';
import Template from '../../../components/templates/Quickstart';
import Markdown from '../../../components/Markdown';
import CodeTabs from '../../../components/CodeTabs';
import CodeTab from '../../../components/CodeTab';
import QuickstartBranch from '../../../components/QuickstartBranch';
import image from '../../../assets/images/quickstart/filtering/final.png';
import imageBug from '../../../assets/images/quickstart/websockets/step-2-bug.png';

export default (props) => {
  return (
    <Template>
      <h1>
        Step 2: Send Client ID to API
      </h1>
      <p>
        In this step we'll update our application so that we no longer see a duplicate tweet when creating a
        new tweet.
      </p>

      <QuickstartBranch branch="websockets.2" />

      <h2>
        What's the problem?
      </h2>
      <p>
        If you open two browser tabs, and create a tweet, you'll notice that the browser that creates the tweet
        ends up with a duplicate tweet in the Feed, where one tweet is real, and the other has the faded effect
        we created as an optimistic visual cue:
      </p>

      <img className="drop-shadow" src={imageBug} />

      <h3>
        Why is this happening?
      </h3>
      <p>
        The short answer is that using optimistic updates alongside websockets is <strong>very</strong> tricky.
        The reason optimistic updates worked correctly <em>before</em> we integrated websockets was because we
        were able to associate the optimistic data that we injected into the application early, with the real data
        that came back from the REST API, and we did this using the <code>cid</code> on the model
        (e.g. <code>c1</code>, <code>c2</code>, etc.)
      </p>
      <p>
        But since this <code>cid</code> doesn't exist on the data that arrives via websockets, then if the websocket
        response returns before the API response from the REST API, we end up with two tweets in the store. One
        has a <code>cid</code> but no <code>id</code> (the optimistic tweet) and the other has an <code>id</code> but
        no <code>cid</code> (the websocket tweet).
      </p>
      <p>
        Because of that, we can't associate those two tweets as the same thing, and we end up with an optimistic
        tweet in the store that will never be resolved.
      </p>

      <h3>
        How do we solve this?
      </h3>
      <p>
        In order to solve this, we need to <strong>send a unique cid to the server</strong>, that it will include
        in the data sent via websockets. This will allow us to associate the optimistic tweet (that has
        no <code>id</code>) with the data coming in through websockets, as long as that data includes
        the <code>cid</code> we sent.
      </p>

      <blockquote>
        <p>
          Some applications will actually allow the client to generate the <code>id</code> of the resource themselves,
          using a <code>UUID</code>, which allows it to be broadcasted to other listeners before being persisted to
          a database.
        </p>
      </blockquote>

      <h3>
        Include cid in API calls
      </h3>
      <p>
        The first step is to include the <code>cid</code> in the data we sent to the API. To do that,
        open <code>config/actions.js</code>, and find the attribute named <code>addCidToBody</code>. Change
        that value to <code>true</code>, like this:
      </p>

      <Markdown text={`
      // config/actions.js
      export default {
        addCidToBody: true
      }
      `}/>

      <p>
        With that change in place, if you create a tweet, you'll notice the <code>cid</code> is included in the
        attributes sent to the APi.
      </p>


      <h3>
        Install UUID Generator
      </h3>
      <p>
        The second problem we need to solve is making that <code>cid</code> unique, and unfortunately,
        the <code>cid</code> values generated by default are only unique for a single browser, and only as long
        as you don't refresh the browser (the first <code>cid</code> is always <code>c1</code>, the second
        is always <code>c2</code>, etc.)
      </p>
      <p>
        To generate a unique cid, we're going to use a package called <code>node-uuid</code> to generate a UUID
        (universally unique identifier). A UUID is a value generated by an algorithm that is essentially guaranteed
        to never be repeated.
      </p>
      <p>
        Install <code>node-uuid</code> using the command below:
      </p>

      <Markdown text={`
      npm install node-uuid --save
      `}/>

      <h3>
        Make cid globally unique
      </h3>
      <p>
        With <code>node-uuid</code> installed, we can now change the algorithm that generates the <code>cid</code> to
        make it a UUID instead of something like <code>c1</code>.
      </p>
      <p>
        To do that, open <code>config/connections.js</code>. Import <code>node-uuid</code>, and update
        the <code>generateCid()</code> function to look like this:
      </p>

      <Markdown text={`
      // config/connections.js
      import uuid from 'node-uuid';
      ...
      export default {

        default: {
          ...
          models: {
            properties: {
              generateCid: function() {
                return uuid.v4();
              }
            }
          },
          ...
        }

      };
      `}/>
      <p>
        That's it! With that change in place, not only will the cid for your models be sent to the server, but
        the <code>cid</code> values will now look like <code>c69b66e8-14e1-4257-a43b-f8acbe6f2635</code> instead
        of <code>c1</code>, and will be unique for every resource, regardless of where or when it was generated.
      </p>

      <h3>
        Visual Check-in
      </h3>
      <p>
        If everything went well, your application should now look like this (the same as before) but you will no
        longer see duplicate tweets when creating data.
      </p>

      <img className="drop-shadow" src={image} />


      <h2>
        Code Changes
      </h2>

      <p>
        Below is a list of files modified during this step.
      </p>

      <h3>
        config/actions.js
      </h3>
      <Markdown text={`
      export default {
        addCidToBody: true
      }
      `}/>

      <h3>
        config/connections.js
      </h3>
      <Markdown text={`
      import uuid from 'node-uuid';
      import auth from '../src/utils/auth';

      export default {

        default: {

          apiRoot: 'http://localhost:1337',

          headers: function() {
            return {
              Authorization: \`Bearer \$\{auth.getToken()\}\`
            };
          },

          models: {
            properties: {
              generateCid: function() {
                return uuid.v4();
              }
            }
          },

          collections: {
            properties: {
              parse: function(response) {
                this.meta = {
                  totalCount: response.meta.paginate.totalCount,
                  perPage: response.meta.paginate.perPage,
                  nextPage: response.meta.paginate.nextPage
                };
                return response.data;
              }
            }
          }

        }

      };
      `}/>

      <h2>
        Next Steps
      </h2>
      <p>
        In the next section we'll learn how to <Link to="../../publishing/overview/">build and deploy the
        application for production</Link>.
      </p>
    </Template>
  )
};
