Skip to content

Instantly share code, notes, and snippets.

@English3000
Last active December 17, 2017 00:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save English3000/d92571382d9b694e8105fd0a49cb24fd to your computer and use it in GitHub Desktop.
Save English3000/d92571382d9b694e8105fd0a49cb24fd to your computer and use it in GitHub Desktop.
State Shape and SQL

When building an app, there's a frontend and a backend. Under the React framework/library, a frontend consists of a hierarchy of components. The frontend is built with HTML, CSS, JavaScript, and JSX. The HTML is for a static page which components will be rendered on. Components are built in JSX.

When you have your hierarchy built and styling set, you can then give components access to data from your backend. My background is with Ruby on Rails, but almost any backend will use some sort of structured-query language to make requests to its database.

The data returned then gets filtered through reducer files into a data structure called the state. Under Redux, state is unidirectional (the frontend can't modify state on its own; the state is modified through responses to API/AJAX requests).

The state is an object version of a SQL table. The state has slices, top-level key-value pairs.

// state
{
  slice: { /* */ }
}

Keys correspond to SQL table names.

Because objects (hashes in Ruby) are accessed via their keys, in order for a table's rows of data to be accessible, its corresponding slice is set to an object of primary key-data entry pairs.

  slice: {
    #: { id: #, /* */ },
    #: { id: #, /* */ }
  }

For each of a table's columns, the column name is paired with the value of that entry.

In a SQL table, there are foreign keys. For example, a post may belong to a user (thus, it has a user_id). In a Redux state, aka a store, foreign keys are instead represented in the users slice.

A user has many posts, and the posts slice is an object of objects. In order to access a user's posts, the posts slice must be keyed into. As a result, each user will have an additional key-value pair for each of its has-many associations (a user has many posts). This key-value pair will consist of the name of the association set to an array of ids (acting as foreign keys from the associated table).

// store
{

  users: {
    1: { 
      id: 1, 
      posts: [1, 2]
    }
  },
  
  posts: {
    1: {
      id: 1,
      body: /* */
    }, 2: {
      id: 2,
      body: /* */
    }
  }
  
}

users

Column
id

posts

Column
id
user_id
body

A second pattern you'll sometimes use is a slice that is not a table with two or more subslices that are tables.

  slice: {
    posts: { /* */ },
    comments: { /* */ }
  }

In this example, a post has many comments. However, all comments are dependent upon their posts. A comment is made on a post. If there were no posts, there would be no comments. As a result of this dependent relation, when querying the database for posts, it often makes sense to also return those posts' associated comments. This is because it saves a query to the database, and in this example, you'll likely want to see the comments with any post.

One last case I'll mention is a many-to-many association via a joins table.

A user has many posts. A post belongs to a user (so it has a foreign key pointing to its author). But a user can like many posts and a post can have likes from many users.

likes

Column
id
user_id
post_id

For the post, what is relevant is its total number of likes. So, each post in the posts slice will have an additional key-value pair of likes set to an integer (a count of how many users have liked this post).

    1: {
      id: 1,
      body: /* */,
      likes: 3
    }

Also, having a joins table implies that on the frontend, the user can like a post by clicking a button. Clicking the button should create a like IF the user HASN'T liked this post. But if the user has, then clicking it should destroy the like (unliking the post). In order to tell whether or not a user has liked a post, we'll need an additional key-value pair for each user in our users slice--liked posts set to an array of post ids.

    1: {
      id: 1,
      posts: [1, 2],
      liked_posts: [1, 2, 3]
    }

The user makes the like (and has an array of post ids); the post receives the like (and has a count of its total likes).

This user likes all of their own posts!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment