<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[How I Get It… - Medium]]></title>
        <description><![CDATA[JavaScript, React.js and Ruby on Rails Principles - Medium]]></description>
        <link>https://medium.com/how-i-get-it?source=rss----4bb7a38a151---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>How I Get It… - Medium</title>
            <link>https://medium.com/how-i-get-it?source=rss----4bb7a38a151---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 01 Jun 2026 05:24:05 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/how-i-get-it" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[React with Rails User Authentication]]></title>
            <link>https://medium.com/how-i-get-it/react-with-rails-user-authentication-8977e98762f2?source=rss----4bb7a38a151---4</link>
            <guid isPermaLink="false">https://medium.com/p/8977e98762f2</guid>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[http-cookie]]></category>
            <category><![CDATA[user-authentication]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Alejandro Sabogal]]></dc:creator>
            <pubDate>Mon, 11 Nov 2019 18:46:24 GMT</pubDate>
            <atom:updated>2019-12-17T20:58:19.501Z</atom:updated>
            <content:encoded><![CDATA[<h4>A comprehensive full-stack User authorization guide</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Wz78RnCS56IS7IZBaZkKDw.png" /><figcaption>Image by <a href="https://pixabay.com/users/geralt-9301/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=3938429">Gerd Altmann</a> from <a href="https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=3938429">Pixabay</a></figcaption></figure><p>Architecting a User authentication service on the Rails backend is very straightforward, but it can be a bit challenging to implement this system on the React client/front-end side of the application.</p><p>In this article, I show you how to build an authentication system for a React with Rails application using HTTP Cookies and the Rails Session Data. Now, you may be wondering about JWT or JSON Web Tokens, and although that approach seems to be the most popular, I think using session data is more practical and secure. For example, If a User password is hacked, with JWT we would have to wait for the token to expire before we could 100% remove access to the User account. With session data, we can simply delete all browser cookies and all the server’s session data associated with that User and immediately block access to the account with the hacked credentials. However, there are some benefits with using JWT over Session data. You should do some research and decide which method works best for you.</p><p>Ok, let’s start building!</p><h3><strong>Pt. 1 — Rails Setup</strong></h3><p><em>We’ll be working with Rails 5, but these techniques should also work on Rails 6.</em></p><p>First, let’s create a new rails project. On your terminal, navigate to your working directory and run the rails new command:</p><pre>rails new your-app-name-api --database=postgresql</pre><p>Notice we are using postgresql for the database. This will make your life much easier when it comes time to deploy your app. I wrote another article on deploying a React + Rails application here: <a href="https://medium.com/how-i-get-it/rails-react-js-heroku-deployment-43d7469e122e">https://medium.com/how-i-get-it/rails-react-js-heroku-deployment-43d7469e122e</a></p><p>Also notice we didn’t use the --api flag. We don’t want to initiate an API only application. This would prevent us from using the Rails Session without installing more dependencies. Below we’ll go over how to configure the app to behave like a real API server.</p><p>Once the rails new command is finished building the file structure, we need to install two essential gems: bcryt and rack-cors. Add these to your gemfile and run bundle in your terminal to install them:</p><pre>#Gemfile</pre><pre>gem &#39;bcrypt&#39;</pre><pre>gem &#39;rack-cors&#39;</pre><p>CORS (Cross Origin Resource Sharing) will allow you to whitelist the origin of requests that can communicate with our Rails backend. Since we’ll be fetching server data originating from the front-end client, we need to configure CORS to allow the front-end to access and post data on the backend, and since we are dealing with authentication, we also want to prevent any other origins from communicating with the server.</p><p>In the config/initializers folder, create a new file called cors.rb and write the following:</p><pre>Rails.application.config.middleware.insert_before 0, Rack::Cors do <br>  allow do<br>    origins &#39;<a href="http://localhost:3000&#39;">http://localhost:3000&#39;</a><br>  <br>    resource &#39;*&#39;,<br>      headers: :any,<br>      methods: [:get, :post, :put, :patch, :delete, :options, :head],<br>      credentials: true<br>  end<br>end</pre><p>By default, your React client will run on <a href="http://localhost:3000">http://localhost:3000</a>. This code allows requests originating from that address to have access to all server resources (&#39;*&#39;) and utilize all HTTP methods: :get, :post, :put, :patch, :delete, :options, :head. <em>This configuration is ideal while you are working on the development environment. Once your application is ready for production, you will need to change the origin to your deployed front-end client’s domain address.</em></p><p>We now need to configure the way our server will handle the HTTP cookies. To do so, in the same config/initializers folder, create a new file called session_store.rb. The server needs to know two things about the cookie; its key and domain. <em>Note, the </em><em>domain is only needed when the app is in production or deployed:</em></p><pre>if Rails.env === &#39;production&#39; <br>  Rails.application.config.session_store :cookie_store, key: &#39;_your-app-name&#39;, domain: &#39;your-frontend-domain&#39;<br>else<br>  Rails.application.config.session_store :cookie_store, key: &#39;_your-app-name&#39; <br>end</pre><p><em>By convention, the key name is your application’s name and should start with an underscore.</em></p><p>Another thing we should change, is the default port for our Rails server. Rails 5 uses Puma to run the server, so in the config/puma.rb file, change the default port to 3001: port <em>ENV</em>.fetch(“PORT”) { 3001 }</p><p>This will prevent our back-end and front-end applications from attempting to run on the same port.</p><p>With this, and the two files above, we’ve now configured the Rails backend server to behave like a secure API.</p><p><strong>Bcrypt and the User Model</strong></p><p>Now that the server is configured, we can build a User model and migrate it to the database. In the terminal:</p><pre>rails g model User username email password_digest</pre><p>Note we used password_digest instead of password. By doing this we are instructing the bcrypt gem to encrypt the User’s password. bcrypt uses a process called ‘salt’ to hash and encrypt passwords. You can learn more about it here: <a href="https://auth0.com/blog/hashing-in-action-understanding-bcrypt/">https://auth0.com/blog/hashing-in-action-understanding-bcrypt/</a>. For now, all you need to know is that bcrypt will secure our passwords.</p><p>We can now create and migrate our database with the User model. Make sure your postgres db client is running, otherwise you’ll run onto errors. In the terminal:</p><pre>rake db:create &amp;&amp; rake db:migrate</pre><p>Check that your schema and database migrations were done correctly. If so, there is one more bcrypt configuration to do. bcrypt uses an attribute called has_secure_password We need to include this in our User model in order for bcrypt to work. While we are at it, let’s also add some validations. In app/model/user.rb :</p><pre>class User &lt; ApplicationRecord<br>  has_secure_password</pre><pre>validates :username, presence: true<br>validates :username, uniqueness: true<br>validates :username, length: { minimum: 4 }<br>validates :email, presence: true<br>validates :email, uniqueness: true</pre><pre>validates_format_of :email, :with =&gt; /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i<br>end</pre><p>Our validations prevent Users from entering invalid or empty data, and return errors that we can present to Users. With this setup, our User model is complete. Let’s add its corresponding routes. I think we should only allow Users to create a new User, see that User and all other Users. They shouldn’t be allowed to edit or delete the user information, so we will allow the following routes in config/routes.rb</p><pre>Rails.application.routes.draw do</pre><pre>  resources :users, only: [:create, :show, :index]</pre><pre>end</pre><p>Let’s now connect the Users Controller. Inside app/controllers create the users_controller.rb file. <em>Please note I’m assuming you are familiar with these methods as they are basic Rails knowledge…</em></p><pre>class UsersController &lt; ApplicationController</pre><pre>def index<br>    @users = User.all<br>    if <a href="http://twitter.com/user">@user</a>s<br>      render json: {<br>        users: <a href="http://twitter.com/user">@user</a>s<br>      }<br>    else<br>      render json: {<br>        status: 500,<br>        errors: [&#39;no users found&#39;]<br>      }<br>    end</pre><pre>end</pre><pre>def show<br>    <a href="http://twitter.com/user">@user</a> = User.find(params[:id])<br>   if <a href="http://twitter.com/user">@user</a><br>      render json: {<br>        user: <a href="http://twitter.com/user">@user</a><br>      }<br>    else<br>      render json: {<br>        status: 500,<br>        errors: [&#39;user not found&#39;]<br>      }<br>    end<br>  end<br>  <br>  def create<br>    <a href="http://twitter.com/user">@user</a> = User.new(user_params)<br>    if <a href="http://twitter.com/user">@user</a>.save<br>      login!<br>      render json: {<br>        status: :created,<br>        user: <a href="http://twitter.com/user">@user</a><br>      }<br>    else <br>      render json: {<br>        status: 500,<br>        errors: <a href="http://twitter.com/user">@user</a>.errors.full_messages<br>      }<br>    end<br>  end</pre><pre>private<br>  <br>  def user_params<br>    params.require(:user).permit(:username, :email, :password, :password_confirmation)<br>  end</pre><pre>end</pre><p>A couple of things to note here, one, I’m only rendering JSON objects because we won’t be using our Rails views. We want to treat our server as an API only app, so we pass the JSON objects to our React client for it to handle displaying them. Two, I’m handling errors in a very basic and semantic way. How you chose to handle errors is up to you. And three, I’m using a helper method login! to create a User. This method inherits from the Application Controller, where I have additional helper methods that will be useful later on. Let’s add them to application_controller.rb:</p><pre>class ApplicationController &lt; ActionController::Base</pre><pre>  skip_before_action :verify_authenticity_token</pre><pre>  helper_method :login!, :logged_in?, :current_user, :authorized_user?, :logout!</pre><pre>def login!<br>    session[:user_id] = <a href="http://twitter.com/user">@user</a>.id<br>  end</pre><pre>def logged_in?<br>    !!session[:user_id]<br>  end</pre><pre>def current_user<br>    <a href="http://twitter.com/current_user">@current_user</a> ||= User.find(session[:user_id]) if session[:user_id]<br>  end</pre><pre>def authorized_user?<br>     <a href="http://twitter.com/user">@user</a> == current_user<br>   end</pre><pre>def logout!<br>     session.clear<br>   end</pre><pre>end</pre><p>There are a lot of important things going on here. Let’s start from the top: the skip_before_action :verify_authenticity_token command prevents Rails from using its authenticity token. This is a security token that Rails generates from our session data and adds to the parameters sent from a Rails form to a controller action to prevent cross-site request forgery (CSRF) attacks. Since we are treating our back-end as an API, we should disable this so that we don’t receive ‘forbidden’ parameters that will prevent our controller actions from executing without errors.</p><p>Next, we have: helper_method :login!, :logged_in?, :current_user, :authorized_user?, :logout! All this is doing is making sure the methods we define below will be passed to all other controllers in the app.</p><p>The login!, logged_in?, current_user, authorized_user?, logout! methods are pretty self explanatory; we are creating a session or deleting it, or we are authorizing a User based on the session data. These methods will be helpful when dealing with the sessions controller. Let’s write that next.</p><p><strong>The Sessions Controller</strong></p><p>Create a sessions_controller.rb file under app/controllers and write the following:</p><pre>class SessionsController &lt; ApplicationController</pre><pre>def create<br>    <a href="http://twitter.com/user">@user</a> = User.find_by(email: session_params[:email])<br>  <br>    if <a href="http://twitter.com/user">@user</a> &amp;&amp; <a href="http://twitter.com/user">@user</a>.authenticate(session_params[:password])<br>      login!<br>      render json: {<br>        logged_in: true,<br>        user: <a href="http://twitter.com/user">@user</a><br>      }<br>    else<br>      render json: { <br>        status: 401,<br>        errors: [&#39;no such user&#39;, &#39;verify credentials and try again or signup&#39;]<br>      }<br>    end<br>  end</pre><pre>def is_logged_in?<br>    if logged_in? &amp;&amp; current_user<br>      render json: {<br>        logged_in: true,<br>        user: current_user<br>      }<br>    else<br>      render json: {<br>        logged_in: false,<br>        message: &#39;no such user&#39;<br>      }<br>    end<br>  end</pre><pre>def destroy<br>    logout!<br>    render json: {<br>      status: 200,<br>      logged_out: true<br>    }<br>  end</pre><pre>private</pre><pre>def session_params<br>    params.require(:user).permit(:username, :email, :password)<br>  end</pre><pre>end</pre><p>This controller’s purpose is to deal with the User’s Log In and Log Out functionality. Again, I only render JSON objects and handle errors in a very basic way. The .authenticate method works hand in hand with the User model’s has_secure_password method to authenticate the password.</p><p>These controller actions need their routes, so let’s write those:</p><pre>Rails.application.routes.draw do</pre><pre>  post &#39;/login&#39;, to: &#39;sessions#create&#39;<br>  delete &#39;/logout&#39;, to: &#39;sessions#destroy&#39;<br>  get &#39;/logged_in&#39;, to: &#39;sessions#is_logged_in?&#39;<br>  <br>  resources :users, only: [:create, :show, :index]</pre><pre>end</pre><p>The /logged_in route and corresponding action will come to play later when we design the User registration system in the React front-end. For now, just know that it will render a boolean to confirm that the User is authenticated and logged in and if so, it responds with the user object too.</p><h3>Pt. 2— React Setup</h3><p>A few notes before we begin the React part of this article:</p><ul><li>I’m assuming you are familiar with React basics like create-react-app, class vs functional components, props and state basics.</li><li>I’m assuming you have npm or yarn installed in your system. We’ll use yarn in this article.</li><li>We’ll use the ‘axios’ dependency for out HTTP requests to the server, and ‘react-router’ and ‘react-router-dom’ to manage our routes.</li><li>We are going to keep the app’s style to a minimum as it’s really not relevant to this topic.</li><li>We’ll use four components: App.js, Home.js, Login.js, Signup.js. Our App.js component will handle most of the apps logic and routing.</li></ul><p>Let’s start by creating our React app. In your terminal:</p><p>npx-create-react-app your-app-name-client &amp;&amp; cd your-app-name-client</p><p>I tend to clean up and remove all the unnecessary files this scaffold comes with, i.e. App.css, App.test.js, logo.svg, serviceWorker.js This is my preference, but you decide how to initiate your app. Also I’m removing the serviceWorker because we won’t need it at all here.</p><p>I then also clean the App.js file to initiate like this:</p><pre>import React from &#39;react&#39;;</pre><pre>function App() {<br>  return (<br>   &lt;div&gt;<br>     <br>   &lt;/div&gt;<br>  );<br>}</pre><pre>export default App;</pre><p>And in index.js, we still pass App.js to the root element and clean the file as such:</p><pre>import React from &#39;react&#39;;<br>import ReactDOM from &#39;react-dom&#39;;<br>import App from &#39;./App&#39;;</pre><pre>ReactDOM.render(&lt;App /&gt;, document.getElementById(&#39;root&#39;));</pre><p>You may also want to make some changes to your public folder, like changing the app’s name on index.html and manifest.json, and remove the unused logos.</p><p>Now let’s add the dependencies we need for our app. In your terminal:</p><p>yarn add axios &amp;&amp; yarn add react-router &amp;&amp; yarn add react-router-dom</p><p>Alright, so now that the app is setup, let’s start developing the authorization system.</p><p><strong>Initial App Logic</strong></p><p>We are going to establish the application’s logic in the App.js component. We will need to change to a class component to manage state, and we will need to import our dependencies axios plus {BrowserRouter, Switch, Route} from react-router-dom. The initial setup for our App.js component should now look like this:</p><pre>import React, { Component } from &#39;react&#39;;<br>import axios from &#39;axios&#39;<br>import {BrowserRouter, Switch, Route} from &#39;react-router-dom&#39;</pre><pre>class App extends Component {<br>  constructor(props) {<br>    super(props);<br>    this.state = { <br>      isLoggedIn: false,<br>      user: {}<br>     };<br>  }</pre><pre>  render() {<br>    return (<br>      &lt;div&gt;<br>         &lt;BrowserRouter&gt;<br>          &lt;Switch&gt;<br>            &lt;Route exact path=&#39;/&#39; component={}/&gt;<br>            &lt;Route exact path=&#39;/login&#39; component={}/&gt;<br>            &lt;Route exact path=&#39;/signup&#39; component={}/&gt;<br>          &lt;/Switch&gt;<br>        &lt;/BrowserRouter&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default App;</pre><p>Our App.js component is not going to render itself to the DOM, instead, it will serve as our router to render all other components. It will also manage the application’s state and authentication status; we use the component’s state to maintain the logged in status of a User, and to store the User data when we request it from the server. You may have noticed that the Routes aren’t rendering any components yet. We’ll build those and include them here later on.</p><p>Let’s add more functionality to the component. Let’s write two methods to interact with the app’s state:</p><pre>handleLogin = (data) =&gt; {<br>    this.setState({<br>      isLoggedIn: true,<br>      user: data.user<br>    })<br>  }</pre><pre>handleLogout = () =&gt; {<br>    this.setState({<br>    isLoggedIn: false,<br>    user: {}<br>    })<br>  }</pre><p>With these methods we now control the login status of the application and the User data. As you can see in the handleLogin() method, we are passing a data argument. This is the response data we receive from the server. So you can think of these methods as being dependent of other functions and other return values. So how do we get this server response data? Let’s add another method to our component:</p><pre>loginStatus = () =&gt; {<br>    axios.get(&#39;<a href="http://localhost:3001/logged_in&#39;">http://localhost:3001/logged_in&#39;</a>, <br>   {withCredentials: true})</pre><pre>    .then(response =&gt; {<br>      if (response.data.logged_in) {<br>        this.handleLogin(response)<br>      } else {<br>        this.handleLogout()<br>      }<br>    })<br>    .catch(error =&gt; console.log(&#39;api errors:&#39;, error))<br>  }</pre><p>This method is very important! It is the backbone of our front-end authorization system. You’ll notice it’s a very straightforward fetch ‘GET’ request using axios, but you can see that we are also passing another argument {withCredentials: true}; <strong><em>this is the key here! This allows our Rails server to set and read the cookie on the front-end’s browser. ALWAYS pass this argument!</em></strong><em> </em>Also notice the http address we are requesting. Remember our Rails /logged_in route and its corresponding controller action?:</p><pre>def is_logged_in?<br>    if logged_in? &amp;&amp; current_user<br>      render json: {<br>        logged_in: true,<br>        user: current_user<br>      }<br>    else<br>      render json: {<br>        logged_in: false,<br>        message: &#39;no such user&#39;<br>      }<br>    end<br>  end</pre><p>Our React App.js component communicates with Rails through this route and controller action. If the User is verified in the Rails server, then a logged_in boolean is returned, along with the user object. App.js uses this response data to maintain the logged in status in the front-end. We need to ‘automate’ this request though. App.js should keep track of this status and request this information every time it’s mounted. We can use the componentDidMount() lifecycle method to call on loginStatus() and achieve this:</p><pre>componentDidMount() {<br>    this.loginStatus()<br>  }</pre><p>With this, our App.js component should look like this:</p><pre>import React, { Component } from &#39;react&#39;;<br>import axios from &#39;axios&#39;<br>import {BrowserRouter, Switch, Route} from &#39;react-router-dom&#39;</pre><pre>class App extends Component {<br>  constructor(props) {<br>    super(props);<br>    this.state = { <br>      isLoggedIn: false,<br>      user: {}<br>     };<br>  }</pre><pre>componentDidMount() {<br>  this.loginStatus()<br>}</pre><pre>  loginStatus = () =&gt; {<br>    axios.get(&#39;<a href="http://localhost:3001/logged_in&#39;">http://localhost:3001/logged_in&#39;</a>, <br>    {withCredentials: true})</pre><pre>    .then(response =&gt; {<br>      if (response.data.logged_in) {<br>        this.handleLogin(response)<br>      } else {<br>        this.handleLogout()<br>      }<br>    })<br>    .catch(error =&gt; console.log(&#39;api errors:&#39;, error))<br>  }</pre><pre>handleLogin = (data) =&gt; {<br>    this.setState({<br>      isLoggedIn: true,<br>      user: data.user<br>    })<br>  }</pre><pre>handleLogout = () =&gt; {<br>    this.setState({<br>    isLoggedIn: false,<br>    user: {}<br>    })<br>  }<br>  <br>  render() {<br>    return (<br>      &lt;div&gt;<br>         &lt;BrowserRouter&gt;<br>          &lt;Switch&gt;<br>            &lt;Route exact path=&#39;/&#39; component={}/&gt;<br>            &lt;Route exact path=&#39;/login&#39; component={}/&gt;<br>            &lt;Route exact path=&#39;/signup&#39; component={}/&gt;<br>          &lt;/Switch&gt;<br>        &lt;/BrowserRouter&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default App;</pre><p>We now have the main authentication logic for the app, however, all this is useless without a way for the user to Sign Up, Log In, and Log Out. For this, inside src/components, let’s make a Home.js file. Also inside, src/components, let’s create a new folder called registrations, and inside of it, let’s add Signup.js and Login.js files.</p><p><strong>The Home Component</strong></p><p>This will be a very basic functional component:</p><pre>import React from &#39;react&#39;;<br>import {Link} from &#39;react-router-dom&#39;</pre><pre>const Home = () =&gt; {<br>  return (<br>    &lt;div&gt;<br>      &lt;Link to=&#39;/login&#39;&gt;Log In&lt;/Link&gt;<br>      &lt;br&gt;&lt;/br&gt;<br>      &lt;Link to=&#39;/signup&#39;&gt;Sign Up&lt;/Link&gt;<br>    &lt;/div&gt;<br>  );<br>};</pre><pre>export default Home;</pre><p>Very simple. We just render two links using the Link component from react-router-dom. These links point to the /signup and /login routes which will render their respective components. Let’s build those components:</p><p><strong>Registration System</strong></p><p>The Signup.js and Login.js components will handle the User signup and login functionality through the use of controlled forms. Users are presented with a form to enter their credentials, and then these are sent to the server for validation.</p><p><em>A quick note here. These two components are almost identical. To keep the code ‘DRY’, we could use a Higher Order Component, or use Styled Components to pass repeating elements, but this is beyond the scope of this article and as such, we’ll just use two separate components.</em></p><p><strong>Login.js:</strong></p><pre>import React, { Component } from &#39;react&#39;;<br>import axios from &#39;axios&#39;<br>import {Link} from &#39;react-router-dom&#39;</pre><pre>class Login extends Component {<br>  constructor(props) {<br>    super(props);<br>    this.state = { <br>      username: &#39;&#39;,<br>      email: &#39;&#39;,<br>      password: &#39;&#39;,<br>      errors: &#39;&#39;<br>     };<br>  }</pre><pre>handleChange = (event) =&gt; {<br>    const {name, value} = event.target<br>    this.setState({<br>      [name]: value<br>    })<br>  };</pre><pre>handleSubmit = (event) =&gt; {<br>    event.preventDefault()<br>  };</pre><pre>render() {<br>    const {username, email, password} = this.state</pre><pre>return (<br>      &lt;div&gt;<br>        &lt;h1&gt;Log In&lt;/h1&gt;</pre><pre>        &lt;form onSubmit={this.handleSubmit}&gt;<br>          &lt;input<br>            placeholder=&quot;username&quot;<br>            type=&quot;text&quot;<br>            name=&quot;username&quot;<br>            value={username}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input<br>            placeholder=&quot;email&quot;<br>            type=&quot;text&quot;<br>            name=&quot;email&quot;<br>            value={email}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input<br>            placeholder=&quot;password&quot;<br>            type=&quot;password&quot;<br>            name=&quot;password&quot;<br>            value={password}<br>            onChange={this.handleChange}<br>          /&gt;</pre><pre>         &lt;button placeholder=&quot;submit&quot; type=&quot;submit&quot;&gt;<br>            Log In<br>          &lt;/button&gt;</pre><pre>          &lt;div&gt;<br>            or &lt;Link to=&#39;/signup&#39;&gt;sign up&lt;/Link&gt;<br>          &lt;/div&gt;<br>          <br>         &lt;/form&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default Login;</pre><p><strong>Signup.js:</strong></p><pre>import React, { Component } from &#39;react&#39;;<br>import axios from &#39;axios&#39;</pre><pre>class Signup extends Component {<br>  constructor(props) {<br>    super(props);<br>    this.state = { <br>      username: &#39;&#39;,<br>      email: &#39;&#39;,<br>      password: &#39;&#39;,<br>      password_confirmation: &#39;&#39;,<br>      errors: &#39;&#39;<br>     };<br>  }</pre><pre>handleChange = (event) =&gt; {<br>    const {name, value} = event.target<br>    this.setState({<br>      [name]: value<br>    })<br>  };</pre><pre>handleSubmit = (event) =&gt; {<br>    event.preventDefault()<br>  };</pre><pre>render() {<br>    const {username, email, password, password_confirmation} = this.state</pre><pre>return (<br>      &lt;div&gt;<br>        &lt;h1&gt;Sign Up&lt;/h1&gt;</pre><pre>        &lt;form onSubmit={this.handleSubmit}&gt;<br>          &lt;input<br>            placeholder=&quot;username&quot;<br>            type=&quot;text&quot;<br>            name=&quot;username&quot;<br>            value={username}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input<br>            placeholder=&quot;email&quot;<br>            type=&quot;text&quot;<br>            name=&quot;email&quot;<br>            value={email}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input <br>            placeholder=&quot;password&quot;<br>            type=&quot;password&quot;<br>            name=&quot;password&quot;<br>            value={password}<br>            onChange={this.handleChange}<br>          /&gt;</pre><pre>          &lt;input<br>            placeholder=&quot;password confirmation&quot;<br>            type=&quot;password&quot;<br>            name=&quot;password_confirmation&quot;<br>            value={password_confirmation}<br>            onChange={this.handleChange}<br>          /&gt;<br>        <br>          &lt;button placeholder=&quot;submit&quot; type=&quot;submit&quot;&gt;<br>            Sign Up<br>          &lt;/button&gt;<br>      <br>        &lt;/form&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default Signup;</pre><p>Both containers are pretty much the same. They are a basic controlled form, where Signup.js has and additional input field, password_confirmation. This is common when using bcrypt on Rails and it’s good practice in general to have Users confirm their passwords.</p><p>Other things to note about the forms; we are adding an errors attribute to state so we can handle response errors from the server. We are also destructuring the component’s state and the form’s inputs. On handleChange, we use this technique to avoid hardcoding each of the state’s properties while setting state on the input’s change. Also, we are using event.preventDefault() on handleSubmit() to prevent the browser from submitting the form in the usual way. We are going to add some additional logic to this method — and to other parts of the components, so we need to prevent the form from submitting.</p><p>Before we can add this logic to our registrations components, we must expand the App.js component and the router functionality. This component is actively checking the logged in status of the User. What we really want to do, is pass this status to components that require User authentication. The idea is to only render or display authorized data when the User is logged in, so our components will need this information, and with it, we can conditionally display information to the Users. The content you decide to render to your Users based on their logged in status is up to you. Below we expand App.js to be able to pass this status — along with our other App.js methods to our components. We also fully expand the router logic:</p><pre>import React, { Component } from &#39;react&#39;;<br>import axios from &#39;axios&#39;<br>import {BrowserRouter, Switch, Route} from &#39;react-router-dom&#39;<br>import Home from &#39;./components/Home&#39;<br>import Login from &#39;./components/registrations/Login&#39;<br>import Signup from &#39;./components/registrations/Signup&#39;</pre><pre>class App extends Component {<br>  constructor(props) {<br>    super(props);<br>    this.state = { <br>      isLoggedIn: false,<br>      user: {}<br>     };<br>  }</pre><pre>componentDidMount() {<br>    this.loginStatus()<br>  }</pre><pre>  loginStatus = () =&gt; {<br>    axios.get(&#39;<a href="http://localhost:3001/logged_in&#39;">http://localhost:3001/logged_in&#39;</a>, {withCredentials: true})<br>    .then(response =&gt; {<br>      if (response.data.logged_in) {<br>        this.handleLogin(response)<br>      } else {<br>        this.handleLogout()<br>      }<br>    })<br>    .catch(error =&gt; console.log(&#39;api errors:&#39;, error))<br>  }</pre><pre>handleLogin = (data) =&gt; {<br>    this.setState({<br>      isLoggedIn: true,<br>      user: data.user<br>    })<br>  }</pre><pre>handleLogout = () =&gt; {<br>    this.setState({<br>    isLoggedIn: false,<br>    user: {}<br>    })<br>  }</pre><pre>render() {<br>    return (<br>      &lt;div&gt;<br>        &lt;BrowserRouter&gt;<br>          &lt;Switch&gt;<br>            &lt;Route <br>              exact path=&#39;/&#39; <br>              render={props =&gt; (<br>              &lt;Home {...props} loggedInStatus={this.state.isLoggedIn}/&gt;<br>              )}<br>            /&gt;<br>            &lt;Route <br>              exact path=&#39;/login&#39; <br>              render={props =&gt; (<br>              &lt;Login {...props} <em>handleLogin</em>={<em>this</em>.handleLogin} loggedInStatus={this.state.isLoggedIn}/&gt;<br>              )}<br>            /&gt;<br>            &lt;Route <br>              exact path=&#39;/signup&#39; <br>              render={props =&gt; (<br>              &lt;Signup {...props} handleLogin={this.handleLogin} loggedInStatus={this.state.isLoggedIn}/&gt;<br>              )}<br>            /&gt;<br>          &lt;/Switch&gt;<br>        &lt;/BrowserRouter&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default App;</pre><p>We imported our Home.js, Login.js andSignup.js components. We are also now rendering these components using render=props. This allows us to pass props to the components to be rendered, and in that way, we can pass isLoggedIn state status, handleLogin(), and handleLogout(), to our components as props!</p><p><em>Note: you can also pass the User object from state down to the necessary components. Which of your components will need that data is up to you, I’m not passing </em><em>user at this time.</em></p><p><strong>Back to the Registration System</strong></p><p>Now that we have access to App.js&#39;s state and methods, we can expand the functionality of Login.js and Signup.js:</p><p><strong>Login.js:</strong></p><pre>import React, { Component } from &#39;react&#39;;<br>import axios from &#39;axios&#39;<br>import {Link} from &#39;react-router-dom&#39;</pre><pre>class Login extends Component {<br>  constructor(props) {<br>    super(props);<br>    this.state = { <br>      username: &#39;&#39;,<br>      email: &#39;&#39;,<br>      password: &#39;&#39;,<br>      errors: &#39;&#39;<br>     };<br>  }</pre><pre>handleChange = (event) =&gt; {<br>    const {name, value} = event.target<br>    this.setState({<br>      [name]: value<br>    })<br>  };</pre><pre>handleSubmit = (event) =&gt; {<br>    event.preventDefault()<br>    const {username, email, password} = this.state</pre><pre>let user = {<br>      username: username,<br>      email: email,<br>      password: password<br>    }<br>    <br>axios.post(&#39;<a href="http://localhost:3001/login&#39;">http://localhost:3001/login&#39;</a>, {user}, {withCredentials: true})<br>    .then(response =&gt; {<br>      if (response.data.logged_in) {<br>        this.props.handleLogin(response.data)<br>        this.redirect()<br>      } else {<br>        this.setState({<br>          errors: response.data.errors<br>        })<br>      }<br>    })<br>    .catch(error =&gt; console.log(&#39;api errors:&#39;, error))<br>  };</pre><pre>redirect = () =&gt; {<br>    this.props.history.push(&#39;/&#39;)<br>  }</pre><pre>handleErrors = () =&gt; {<br>    return (<br>      &lt;div&gt;<br>        &lt;ul&gt;<br>        {this.state.errors.map(error =&gt; {<br>        return &lt;li key={error}&gt;{error}&lt;/li&gt;<br>          })}<br>        &lt;/ul&gt;<br>      &lt;/div&gt;<br>    )<br>  }</pre><pre>render() {<br>    const {username, email, password} = this.state</pre><pre>return (<br>      &lt;div&gt;<br>        &lt;h1&gt;Log In&lt;/h1&gt;<br>        &lt;form onSubmit={this.handleSubmit}&gt;<br>          &lt;input<br>            placeholder=&quot;username&quot;<br>            type=&quot;text&quot;<br>            name=&quot;username&quot;<br>            value={username}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input<br>            placeholder=&quot;email&quot;<br>            type=&quot;text&quot;<br>            name=&quot;email&quot;<br>            value={email}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input<br>            placeholder=&quot;password&quot;<br>            type=&quot;password&quot;<br>            name=&quot;password&quot;<br>            value={password}<br>            onChange={this.handleChange}<br>          /&gt;</pre><pre>          &lt;button placeholder=&quot;submit&quot; type=&quot;submit&quot;&gt;<br>            Log In<br>          &lt;/button&gt;</pre><pre>          &lt;div&gt;<br>           or &lt;Link to=&#39;/signup&#39;&gt;sign up&lt;/Link&gt;<br>          &lt;/div&gt;<br>          <br>        &lt;/form&gt;<br>        &lt;div&gt;<br>          {<br>            this.state.errors ? this.handleErrors() : null<br>          }<br>        &lt;/div&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default Login;</pre><p><strong>Signup.js:</strong></p><pre>import React, { Component } from &#39;react&#39;;<br>import axios from &#39;axios&#39;</pre><pre>class Signup extends Component {<br>  constructor(props) {<br>    super(props);<br>    this.state = { <br>      username: &#39;&#39;,<br>      email: &#39;&#39;,<br>      password: &#39;&#39;,<br>      password_confirmation: &#39;&#39;,<br>      errors: &#39;&#39;<br>     };<br>  }</pre><pre>handleChange = (event) =&gt; {<br>    const {name, value} = event.target<br>    this.setState({<br>      [name]: value<br>    })<br>  };</pre><pre>handleSubmit = (event) =&gt; {<br>    event.preventDefault()<br>    const {username, email, password, password_confirmation} = this.state<br>    let user = {<br>      username: username,<br>      email: email,<br>      password: password,<br>      password_confirmation: password_confirmation<br>    }</pre><pre>axios.post(&#39;<a href="http://localhost:3001/users&#39;">http://localhost:3001/users&#39;</a>, {user}, {withCredentials: true})<br>    .then(response =&gt; {<br>      if (response.data.status === &#39;created&#39;) {<br>        this.props.handleLogin(response.data)<br>        this.redirect()<br>      } else {<br>        this.setState({<br>          errors: response.data.errors<br>        })<br>      }<br>    })<br>    .catch(error =&gt; console.log(&#39;api errors:&#39;, error))<br>  };</pre><pre>redirect = () =&gt; {<br>    this.props.history.push(&#39;/&#39;)<br>  }</pre><pre>handleErrors = () =&gt; {<br>    return (<br>      &lt;div&gt;<br>        &lt;ul&gt;{this.state.errors.map((error) =&gt; {<br>          return key={error}&gt;{error}&lt;/li&gt;<br>        })}<br>        &lt;/ul&gt; <br>      &lt;/div&gt;<br>    )<br>  }</pre><pre>render() {<br>    const {username, email, password, password_confirmation} = this.state</pre><pre>return (<br>      &lt;div&gt;<br>        &lt;h1&gt;Sign Up&lt;/h1&gt;</pre><pre>       &lt;form onSubmit={this.handleSubmit}&gt;<br>          &lt;input<br>            placeholder=&quot;username&quot;<br>            type=&quot;text&quot;<br>            name=&quot;username&quot;<br>            value={username}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input<br>            placeholder=&quot;email&quot;<br>            type=&quot;text&quot;<br>            name=&quot;email&quot;<br>            value={email}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input <br>            placeholder=&quot;password&quot;<br>            type=&quot;password&quot;<br>            name=&quot;password&quot;<br>            value={password}<br>            onChange={this.handleChange}<br>          /&gt;</pre><pre>          &lt;input<br>            placeholder=&quot;password confirmation&quot;<br>            type=&quot;password&quot;<br>            name=&quot;password_confirmation&quot;<br>            value={password_confirmation}<br>            onChange={this.handleChange}<br>          /&gt;<br>        <br>          &lt;button placeholder=&quot;submit&quot; type=&quot;submit&quot;&gt;<br>            Sign Up<br>          &lt;/button&gt;<br>      <br>        &lt;/form&gt;<br>        &lt;div&gt;<br>          {<br>            this.state.errors ? this.handleErrors() : null<br>          }<br>        &lt;/div&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default Signup;</pre><p>We expanded the same functionality to both Login.js and Signup.js. Let’s break down what we added:</p><p>On handleSubmit(), we are creating a user object based on the component’s state. This is the data argument that axios will POST to the Rails server for authentication. <strong><em>Again, note we are also passing </em></strong><strong><em>{withCredentials: true}. ALWAYS pass this in the header as it’s what allows Rails to set the cookie! </em></strong>We then check the server response and if it’s valid, we can call App.js&#39;s handleLogin() method, which will change the app’s isLogged_in status. Else, the server responds with errors and we set the state’s errors attribute. Since this attribute evaluates to true, the handleErrors() method is called in the component’s render() method and displays these errors to the user:</p><pre>handleErrors = () =&gt; {<br>    return (<br>      &lt;div&gt;<br>        &lt;ul&gt;<br>        {this.state.errors.map(error =&gt; {<br>        return &lt;li key={error}&gt;{error}&lt;/li&gt;<br>          })<br>        }<br>        &lt;/ul&gt;<br>      &lt;/div&gt;<br>    )<br>  }</pre><pre>.<br>.<br>.</pre><pre>render()<br>...</pre><pre>&lt;div&gt;<br>   {<br>     this.state.errors ? this.handleErrors() : null<br>   }<br>&lt;/div&gt;</pre><p>We are also utilizing redirect():</p><pre>redirect = () =&gt; {<br>    this.props.history.push(&#39;/&#39;)<br>  }</pre><p>We built this method so we can redirect the User if the server responds with a valid authentication. We have access to the history props passed to us from react-router-dom when we use render=props on App.js.</p><p>We now have a working authorization system on our React front-end. But how do we really implement it? This is really up to you. Now that we have access to App.js&#39;s isLoggedIn state, we can render or prevent rendering of content. For example, if a User is already logged in, allowing navigation to the /login route, wouldn’t make sense. Let’s prevent that:</p><pre>componentWillMount() {<br>    return this.props.loggedInStatus ? this.redirect() : null<br>  }</pre><p>With this, we prevent a logged in User from navigating to /login. You can see how the logged in status can be used in several ways; allowing or preventing displaying the User page, rendering items on a NavBar, loading User preferences, or rendering a Log Out link for example. Let’s create the Log Out functionality:</p><p>We are going to add a ‘Log Out’ link to the home page in Home.js. Normally though, I would add this link on a NavBar so that is available to Users at anytime.</p><pre>import React from &#39;react&#39;;<br>import {Link} from &#39;react-router-dom&#39;</pre><pre>const Home = (props) =&gt; {</pre><pre>const handleClick = () =&gt; {<br>   // we&#39;ll do handle the logout functionality here<br>  }</pre><pre>return (<br>   <br>    &lt;div&gt;<br>      &lt;Link to=&#39;/login&#39;&gt;Log In&lt;/Link&gt;<br>      &lt;br&gt;&lt;/br&gt;<br>      &lt;Link to=&#39;/signup&#39;&gt;Sign Up&lt;/Link&gt;<br>      &lt;br&gt;&lt;/br&gt;<br>      { <br>        props.loggedInStatus ? <br>        &lt;Link to=&#39;/logout&#39; onClick={handleClick}&gt;Log Out&lt;/Link&gt; : <br>        null<br>      }<br>    &lt;/div&gt;<br>  );<br>};</pre><pre>export default Home;</pre><p>Here, we are displaying the link only if the User is logged in, and we are adding an onClick event that triggers the handleClick function which will handle the logout functionality. This will have to do two things, 1) update the isLoggedIn state in our front-end to false and remove the User data, 2) logout the User on the back-end server.</p><p>App.js already has a handleLogout() method that we can use to update the isLoggedIn state and remove the User. We need to pass this method as a prop to Home.js. To do so, we update the route in App.js:</p><pre>&lt;Route <br>    exact path=&#39;/&#39; <br>    ender={props =&gt; (<br>    &lt;Home {...props} handleLogout={this.handleLogout} //pass prop loggedInStatus={this.state.isLoggedIn}/&gt;)}<br>     /&gt;</pre><p>And now to logout the User on the back-end, we make a request to the server&#39;s /logout route, which triggers the sessions_controller destroy action. We also keep the User on the home page by redirecting to the root route. <strong><em>As ALWAYS, remember to pass </em></strong><strong><em>{withCredentials: true}</em></strong><em>:</em></p><pre>axios.delete(&#39;<a href="http://localhost:3001/logout&#39;">http://localhost:3001/logout&#39;</a>, {withCredentials: true})<br>    .then(response =&gt; {<br>      props.handleLogout()<br>      props.history.push(&#39;/&#39;)<br>    })<br>    .catch(error =&gt; console.log(error))</pre><p>We put it all together and our Home.js component should now look like this:</p><pre>import React from &#39;react&#39;;<br>import axios from &#39;axios&#39;<br>import {Link} from &#39;react-router-dom&#39;</pre><pre>const Home = (props) =&gt; {</pre><pre>const handleClick = () =&gt; {<br>    axios.delete(&#39;<a href="http://localhost:3001/logout&#39;">http://localhost:3001/logout&#39;</a>, {withCredentials: true})<br>    .then(response =&gt; {<br>      props.handleLogout()<br>      props.history.push(&#39;/&#39;)<br>    })<br>    .catch(error =&gt; console.log(error))<br>  }</pre><pre>return (<br>   <br>    &lt;div&gt;<br>      &lt;Link to=&#39;/login&#39;&gt;Log In&lt;/Link&gt;<br>      &lt;br&gt;&lt;/br&gt;<br>      &lt;Link to=&#39;/signup&#39;&gt;Sign Up&lt;/Link&gt;<br>      &lt;br&gt;&lt;/br&gt;<br>      { <br>        props.loggedInStatus ? <br>        &lt;Link to=&#39;/logout&#39; onClick={handleClick}&gt;Log Out&lt;/Link&gt; : <br>        null<br>      }<br>    &lt;/div&gt;<br>  );<br>};</pre><pre>export default Home;</pre><p>And the other components should look like this:</p><p><strong>App.js:</strong></p><pre>import React, { Component } from &#39;react&#39;;<br>import axios from &#39;axios&#39;<br>import {BrowserRouter, Switch, Route} from &#39;react-router-dom&#39;<br>import Home from &#39;./components/Home&#39;<br>import Login from &#39;./components/registrations/Login&#39;<br>import Signup from &#39;./components/registrations/Signup&#39;</pre><pre>class App extends Component {<br>  constructor(props) {<br>    super(props);<br>    this.state = { <br>      isLoggedIn: false,<br>      user: {}<br>     };<br>  }</pre><pre>componentDidMount() {<br>    this.loginStatus()<br>  }</pre><pre>loginStatus = () =&gt; {<br>    axios.get(&#39;<a href="http://localhost:3001/logged_in&#39;">http://localhost:3001/logged_in&#39;</a>, {withCredentials: true})<br>    .then(response =&gt; {<br>      if (response.data.logged_in) {<br>        this.handleLogin(response)<br>      } else {<br>        this.handleLogout()<br>      }<br>    })<br>    .catch(error =&gt; console.log(&#39;api errors:&#39;, error))<br>  }</pre><pre>handleLogin = (data) =&gt; {<br>    this.setState({<br>      isLoggedIn: true,<br>      user: data.user<br>    })<br>  }</pre><pre>handleLogout = () =&gt; {<br>    this.setState({<br>    isLoggedIn: false,<br>    user: {}<br>    })<br>  }</pre><pre>render() {<br>    return (<br>      &lt;div&gt;<br>        &lt;BrowserRouter&gt;<br>          &lt;Switch&gt;<br>            &lt;Route <br>              exact path=&#39;/&#39; <br>              render={props =&gt; (<br>              &lt;Home {...props} handleLogout={this.handleLogout} loggedInStatus={this.state.isLoggedIn}/&gt;<br>              )}<br>            /&gt;<br>            &lt;Route <br>              exact path=&#39;/login&#39; <br>              render={props =&gt; (<br>              &lt;Login {...props} handleLogin={this.handleLogin} loggedInStatus={this.state.isLoggedIn}/&gt;<br>              )}<br>            /&gt;<br>            &lt;Route <br>              exact path=&#39;/signup&#39; <br>              render={props =&gt; (<br>              &lt;Signup {...props} handleLogin={this.handleLogin} loggedInStatus={this.state.isLoggedIn}/&gt;<br>              )}<br>            /&gt;<br>          &lt;/Switch&gt;<br>        &lt;/BrowserRouter&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default App;</pre><p><strong>Login.js:</strong></p><pre>import React, { Component } from &#39;react&#39;;<br>import axios from &#39;axios&#39;<br>import {Link} from &#39;react-router-dom&#39;</pre><pre>class Login extends Component {<br>  constructor(props) {<br>    super(props);<br>    this.state = { <br>      username: &#39;&#39;,<br>      email: &#39;&#39;,<br>      password: &#39;&#39;,<br>      errors: &#39;&#39;<br>     };<br>  }<br>  componentWillMount() {<br>    return this.props.loggedInStatus ? this.redirect() : null<br>  }</pre><pre>handleChange = (event) =&gt; {<br>    const {name, value} = event.target<br>    this.setState({<br>      [name]: value<br>    })<br>  };</pre><pre>handleSubmit = (event) =&gt; {<br>    event.preventDefault()<br>    const {username, email, password} = this.state</pre><pre>let user = {<br>      username: username,<br>      email: email,<br>      password: password<br>    }<br>    <br>    axios.post(&#39;<a href="http://localhost:3001/login&#39;">http://localhost:3001/login&#39;</a>, {user}, {withCredentials: true})<br>    .then(response =&gt; {<br>      if (response.data.logged_in) {<br>        this.props.handleLogin(response.data)<br>        this.redirect()<br>      } else {<br>        this.setState({<br>          errors: response.data.errors<br>        })<br>      }<br>    })<br>    .catch(error =&gt; console.log(&#39;api errors:&#39;, error))<br>  };</pre><pre>redirect = () =&gt; {<br>    this.props.history.push(&#39;/&#39;)<br>  }</pre><pre>handleErrors = () =&gt; {<br>    return (<br>      &lt;div&gt;<br>        &lt;ul&gt;<br>        {this.state.errors.map(error =&gt; {<br>        return &lt;li key={error}&gt;{error}&lt;/li&gt;<br>          })<br>        }<br>        &lt;/ul&gt;<br>      &lt;/div&gt;<br>    )<br>  }</pre><pre>render() {<br>    const {username, email, password} = this.state</pre><pre>return (<br>      &lt;div&gt;<br>        &lt;h1&gt;Log In&lt;/h1&gt;<br>        &lt;form onSubmit={this.handleSubmit}&gt;<br>          &lt;input<br>            placeholder=&quot;username&quot;<br>            type=&quot;text&quot;<br>            name=&quot;username&quot;<br>            value={username}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input<br>            placeholder=&quot;email&quot;<br>            type=&quot;text&quot;<br>            name=&quot;email&quot;<br>            value={email}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input<br>            placeholder=&quot;password&quot;<br>            type=&quot;password&quot;<br>            name=&quot;password&quot;<br>            value={password}<br>            onChange={this.handleChange}<br>          /&gt;</pre><pre>          &lt;button placeholder=&quot;submit&quot; type=&quot;submit&quot;&gt;<br>            Log In<br>          &lt;/button&gt;</pre><pre>          &lt;div&gt;<br>            or &lt;Link to=&#39;/signup&#39;&gt;sign up&lt;/Link&gt;<br>          &lt;/div&gt;<br>          <br>          &lt;/form&gt;<br>          &lt;div&gt;<br>          {<br>            this.state.errors ? this.handleErrors() : null<br>          }<br>        &lt;/div&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default Login;</pre><p><strong>Signup.js</strong></p><pre>import React, { Component } from &#39;react&#39;;<br>import axios from &#39;axios&#39;</pre><pre>class Signup extends Component {<br>  constructor(props) {<br>    super(props);<br>    this.state = { <br>      username: &#39;&#39;,<br>      email: &#39;&#39;,<br>      password: &#39;&#39;,<br>      password_confirmation: &#39;&#39;,<br>      errors: &#39;&#39;<br>     };<br>  }</pre><pre>handleChange = (event) =&gt; {<br>    const {name, value} = event.target<br>    this.setState({<br>      [name]: value<br>    })<br>  };</pre><pre>handleSubmit = (event) =&gt; {<br>    event.preventDefault()<br>    const {username, email, password, password_confirmation} = this.state<br>    let user = {<br>      username: username,<br>      email: email,<br>      password: password,<br>      password_confirmation: password_confirmation<br>    }</pre><pre>axios.post(&#39;<a href="http://localhost:3001/users&#39;">http://localhost:3001/users&#39;</a>, {user}, {withCredentials: true})<br>    .then(response =&gt; {<br>      if (response.data.status === &#39;created&#39;) {<br>        this.props.handleLogin(response.data)<br>        this.redirect()<br>      } else {<br>        this.setState({<br>          errors: response.data.errors<br>        })<br>      }<br>    })<br>    .catch(error =&gt; console.log(&#39;api errors:&#39;, error))<br>  };</pre><pre>redirect = () =&gt; {<br>    this.props.history.push(&#39;/&#39;)<br>  }</pre><pre>handleErrors = () =&gt; {<br>    return (<br>      &lt;div&gt;<br>        &lt;ul&gt;{this.state.errors.map((error) =&gt; {<br>          return &lt;li key={error}&gt;{error}&lt;/li&gt;<br>        })}&lt;/ul&gt; <br>      &lt;/div&gt;<br>    )<br>  }</pre><pre>render() {<br>    const {username, email, password, password_confirmation} = this.state</pre><pre>return (<br>      &lt;div&gt;<br>        &lt;h1&gt;Sign Up&lt;/h1&gt;</pre><pre>        &lt;form onSubmit={this.handleSubmit}&gt;<br>          &lt;input<br>            placeholder=&quot;username&quot;<br>            type=&quot;text&quot;<br>            name=&quot;username&quot;<br>            value={username}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input<br>            placeholder=&quot;email&quot;<br>            type=&quot;text&quot;<br>            name=&quot;email&quot;<br>            value={email}<br>            onChange={this.handleChange}<br>          /&gt;<br>          &lt;input <br>            placeholder=&quot;password&quot;<br>            type=&quot;password&quot;<br>            name=&quot;password&quot;<br>            value={password}<br>            onChange={this.handleChange}<br>          /&gt;</pre><pre>          &lt;input<br>            placeholder=&quot;password confirmation&quot;<br>            type=&quot;password&quot;<br>            name=&quot;password_confirmation&quot;<br>            value={password_confirmation}<br>            onChange={this.handleChange}<br>          /&gt;<br>        <br>          &lt;button placeholder=&quot;submit&quot; type=&quot;submit&quot;&gt;<br>            Sign Up<br>          &lt;/button&gt;<br>      <br>        &lt;/form&gt;<br>        &lt;div&gt;<br>          {<br>            this.state.errors ? this.handleErrors() : null<br>          }<br>        &lt;/div&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default Signup;</pre><p>And that’s it! You now have a working React and Rails User authorization system. I know it’s a long one, but this is a good guide to keep.</p><p><em>Sources:</em></p><p><a href="https://www.udemy.com/user/jordanhudgens/"><strong>Jordan Hudgens</strong></a><strong> </strong>CTO at devCamp</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8977e98762f2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/how-i-get-it/react-with-rails-user-authentication-8977e98762f2">React with Rails User Authentication</a> was originally published in <a href="https://medium.com/how-i-get-it">How I Get It…</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Rails + React.js Heroku Deployment]]></title>
            <link>https://medium.com/how-i-get-it/rails-react-js-heroku-deployment-43d7469e122e?source=rss----4bb7a38a151---4</link>
            <guid isPermaLink="false">https://medium.com/p/43d7469e122e</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[reactjs]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[deployment]]></category>
            <category><![CDATA[heroku]]></category>
            <dc:creator><![CDATA[Alejandro Sabogal]]></dc:creator>
            <pubDate>Thu, 02 May 2019 01:56:54 GMT</pubDate>
            <atom:updated>2019-12-20T22:08:42.308Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j_x-pLE35KCvm6kHd7MyXg.png" /><figcaption>Heroku Platform</figcaption></figure><h3>Deploying a Rails + React.js App to Heroku</h3><p>So you have a finished application that runs on your localhost machine. It’s time now to make your application public and available to users on the web; in essence, to move out of development and into production stage. This isn’t a straight forward task and usually requires some careful tweaking to make sure everything runs smoothly on the web.</p><p>For this article, in an attempt to save you some headaches and countless trial and error commits and erroneous deploys, I will go in-depth on deploying a Rails with React.js application using Heroku.</p><p>Before starting, I’m assuming you’ve done a few things:</p><ol><li>You have a working Rails application with React.js as the client on the same stack that can run on your local environment</li><li>You used the rails new –api command to build the app in API mode (best practice in this case)</li><li>You used create-react-app to build the React client</li><li>Your Ruby version is 2.4.0 or above</li><li>Your Rails version is 5.x</li><li>You know what Heroku is and have set up an account and have their CLI installed</li><li>You have Yarn or NPM installed (we’ll use Yarn in this article)</li></ol><p>Before you can even attempt deploying the app, you must first make some changes to the default configurations in Rails and the overall project in general.</p><p>I suggest you create a separate git branch for these coming changes in case you want to keep your original development version. Once your deployment/production version is complete, you can merge to your master branch.</p><p>Ok, let’s get to it!</p><h4><strong>Changing the Rails Database</strong></h4><p>By default, Rails uses SQLite3 for its database, however, SQLite is not intended as a production-grade database. Heroku works with PostgreSQL, a more robust database. If you’re not familiar with PostgreSQL, I encourage you to research it; it’s really powerful and used by many applications.</p><p>To move from sqlite3to postgres, open your Gemfile and remove or comment out the sqlite3gem and add the postgres gem:</p><p># gem ‘sqlite3’</p><p>gem ‘pg’</p><p>Alternatively, you can group your gems on their respective environments if you want to preserve your current database on the development environment:</p><pre>group :development do<br>    gem ‘sqlite3’<br>end</pre><pre>group :production do<br>    gem ‘pg’<br>end</pre><p>At this point, if you don’t have one, I suggest you create a seed file based on your current database. This will allow you to move or recreate your current data into the new PostgreSQL database. If you plan on having a blank production database, then this won’t be necessary.</p><p>Once your gemfile has been updated, re-install the dependencies by running bundle install in your terminal.</p><p>By adding the postgres gem, we’ve told Rails to start using PostgreSQL as the database. For this to work, you need to change the database adapter from sqlite3 to postgresql in the database configuration file config/database.yml:</p><pre>development:<br>  adapter: postgresql<br>  database: my_database_development<br>  pool: 5<br>  timeout: 5000<br>test:<br>  adapter: postgresql<br>  database: my_database_test<br>  pool: 5<br>  timeout: 5000</pre><pre>production:<br>  adapter: postgresql<br>  database: my_database_production<br>  pool: 5<br>  timeout: 5000</pre><p><em>Note: This setup makes all environments use PostgreSQL. If you want to keep using SQLite on development, leave the development adapter pointing to sqlite3. Also, make sure you substitute “my_database” to your app’s root directory name.</em></p><p>At this point, you should commit your changes to your production branch.</p><h4><strong>ActiveStorage Changes</strong></h4><p>Rails’ ActiveStorage allows you to attach files to ActiveRecord models. If you are using ActiveStorage to attach pictures, audio, or other files, you need to make some configuration changes before deployment. This is because Heroku uses an “ephemeral” disk that allows you to write files to it, however, those files won’t persist after the Heroku app is restarted.</p><p>Instead of storing uploaded files directly on Heroku, it is recommended to use a cloud file storage service such as AWS or Google Cloud. In this article, we’ll use Google Cloud Storage as it’s very straight forward and it’s free to use for the first year.</p><p>Go to <a href="https://cloud.google.com">https://cloud.google.com</a> and sign in with your Google account or create one. You’ll be taken to the Google Cloud Platform where you will create a new project. Name the project as your application’s name:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qedJyvGTEdrFEq0ToKmnOQ.png" /></figure><p>Next, open the Google Cloud Platform menu on the left side. Under “Storage”, hover over “Storage” and click on “Browser”. Click on the “Create Bucket” button to create a new “bucket” for your project:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*r3ccqdjYZ0Vca30xXtE-aA.png" /></figure><p>A bucket is where your data is held on the Google Cloud. The name must be globally unique across Cloud Storage. For the settings, select Regional storage class, choose your location, and create:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Q58d7l3AKw6gdbNbeVDXqQ.png" /></figure><p>Your bucket is now created. Now you have to give it access to your Rails backend. To do so you need to get an authorization key. On the main menu, under API’s &amp; Services”, click on “Credentials”. This will open up a new page to create new credentials; create a new Service account key:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eiEH0sKbSeI6eIj9TkiR8Q.png" /></figure><p>Pick a name for your service account, select Project Owner as the Role, and make sure the Key Type is in JSON format:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JgnZ_44PrQX9QCKiq6-7Og.png" /></figure><p>After clicking “Create”, a public/private key pair is generated and downloaded to your computer. Make sure to keep this in a safe place as it is the only copy of it you will have.</p><p>You now have a working Google Cloud project to upload and host your application’s files. Now let’s set up the Rails backend to work with it:</p><p>You need to let your app know about the authorization keys you just saved. First create a secrets folder inside your app’s config folder.</p><p>Add config/secrets/* to the app’s .gitignorefile. This will prevent the contents of the secrets folder to be included in git version control, and uploaded and shared to git remotes.</p><p>Now rename the downloaded .json file to: your-app-name.json and move it into the config/secretes folder.</p><p>You now need to configure Rails to use the Google Cloud Service. First, add the Google Storage gem to your gemfile:</p><p>gem &quot;google-cloud-storage&quot;, &quot;~&gt; 1.8&quot;, require: false</p><p>And run bundle install in the terminal.</p><p>Next, change the app’s storage configuration file config/storage.yml. Make the following changes:</p><pre>google:<br>     service: GCS<br>     project: your-app-name<br>     credentials: &lt;%= ENV[&#39;GOOGLE_APPLICATION_CREDENTIALS&#39;] %&gt;<br>     bucket: your-app-name</pre><p><em>Note: Make sure you add your corresponding project and bucket names instead of “your-app-name”.</em></p><p>Now, tell Rails to use :google for the production environment. In config/environments/production.rb, make the following change:</p><p>config.active_storage.service = :google</p><p><em>Note: Your development environment will continue to use ActiveStorage. If you want to use Google Cloud for development environment as well, you need to configure Rails to do so:</em></p><pre>google_dev:<br>     service: GCS<br>     project: your-app-name<br>     credentials: &lt;%= Rails.root.join(&quot;config/secrets/ your-app-name.json &quot;) %&gt;<br>     bucket: your-app-name</pre><p>config/environments/development.rb :</p><p>config.active_storage.service = :google_dev</p><p>At this point, if this was a single Rails application, you could create the database and do your migrations, and then deploy it to Heroku. But since we have a React.js client, we need to change a few more things on the backend. This would be a good time to commit your changes.</p><h4><strong>Building the Production Client and Setting Up Rails for Deployment</strong></h4><p>Just as with a single React.js application, the client needs to be built to create a build directory that will hold the app’s production static files. Included in these files will be index.html, which will be served to visitors of the site. These files will be contained on the public folder of the Rails backend, which is what we want to deploy to Heroku. We can use Yarn (or NPM) to create the build and deploy scripts that will prepare our app for production.</p><p>Heroku works very good with Node.js applications and will recognize such apps if it sees a package.json file in the root of the application. Let’s create that file:</p><p>In your terminal and in the project’s root directory, execute yarn init and follow instructions.</p><p>This will add the package.json file to the Rails backend that Heroku will then use to build and deploy the app. It will look something like this:</p><pre>{<br>  &quot;name&quot;: &quot;my-awesome-package&quot;,<br>  &quot;version&quot;: &quot;1.0.0&quot;,<br>  &quot;description&quot;: &quot;The best package you will ever find.&quot;,<br>  &quot;main&quot;: &quot;index.js&quot;,<br>  &quot;repository&quot;: {<br>    &quot;url&quot;: &quot;https://github.com/yarnpkg/example-yarn-package&quot;,<br>    &quot;type&quot;: &quot;git&quot;<br>  },<br>  &quot;author&quot;: &quot;Yarn Contributor&quot;,<br>  &quot;license&quot;: &quot;MIT&quot;<br>}</pre><p>We now need to add the scripts that will be executed for such actions:</p><pre>&quot;scripts&quot;: {<br>    &quot;build&quot;: &quot;cd client &amp;&amp; yarn install &amp;&amp; yarn build &amp;&amp; cd ..&quot;,<br>    &quot;deploy&quot;: &quot;cp -a client/build/. public/&quot;,<br>    &quot;postinstall&quot;: &quot;yarn build &amp;&amp; yarn deploy &amp;&amp; echo &#39;Client built!&#39;&quot;<br>  },</pre><p>When we push our repo to Heroku, Heroku will run npm install while deploying the app to make sure all necessary dependencies are installed. With the scripts above, we are telling Heroku to run the postinstall script after it initially runs npm install. The postinstall script runs the build script which will run yarn install in the client directory to install any dependencies the client may have, and then run yarn build to create the build folder that will hold the static files. Then the deploy script will run and will copy all the build files into the public folder for deployment.</p><p>Heroku also needs to know your version of Yarn, NPM, and Node. To find them use these commands in the terminal:</p><pre>yarn -v &amp;&amp; npm -v &amp;&amp; node -v</pre><p>Then add an engines object to the Rails’ package.json:</p><pre>. . .</pre><pre>&quot;scripts&quot;: {<br>    &quot;build&quot;: &quot;cd client &amp;&amp; yarn install &amp;&amp; yarn build &amp;&amp; cd ..&quot;,<br>    &quot;deploy&quot;: &quot;cp -a client/build/. public/&quot;,<br>    &quot;postinstall&quot;: &quot;yarn build &amp;&amp; yarn deploy &amp;&amp; echo &#39;Client built!&#39;&quot;<br>  },<br>  &quot;engines&quot;: {<br>    &quot;yarn&quot;: &quot;1.21.1&quot;,<br>    &quot;npm&quot;: &quot;6.11.3&quot;,<br>    &quot;node&quot;: &quot;12.11.1&quot;<br>  },</pre><p>With the above instructions, Heroku now knows how to build and deploy the app. We now need to tell it how to run the Rails server once the app is hosted on Heroku. To do this, we need to give it instructions via a Procfile:</p><p>In the app’s root directory, create a file called Procfile (it must be named exactly this way). In the file, write the following line:</p><p>web: bundle exec puma -t 5:5 -p ${PORT:-3001} -e ${RACK_ENV:-development}</p><p>This tells Heroku to run the Rails server on port 3001.</p><p><em>Note: You can set this port to whatever you want. Just make sure it is not the same port your client is using to connect, and that is the same port your fetch/ajax request are using to fetch data from the backend. More on this in the section below.</em></p><h4><strong>Connecting the React Client to the Rails API</strong></h4><p>By default, the Rails server runs on port 3000. So does the client development build when ruining in your local server, i.e. when running yarn start or npm start.</p><p>You might have been running two local servers by executing rails s –p 3001 in your terminal and on your app’s root directory, and yarn start on the client’s root directory. This will allow your client to run on the http://localhost:3000/ and the Rails backend/server on <a href="http://localhost:3001/.">http://localhost:3001/.</a></p><p>This manual setup is ok while on development, but for production, we need to make sure that the client makes the server calls to the right port, every time. To do so, we must add a proxy to the client’s package.json file:</p><pre>{<br>  &quot;name&quot;: &quot;client&quot;,<br>  &quot;version&quot;: &quot;0.1.0&quot;,<br>  &quot;private&quot;: true,<br>  &quot;proxy&quot;: &quot;http://localhost:3001&quot;,<br>  &quot;dependencies&quot;: { <br>	<br>	. . .<br>	<br>	}</pre><p>Next, we need to make changes to the client’s fetch requests.</p><p>You may have a component that makes calls to the Rails API/server. Something similar to this:</p><pre>const apiURL = &#39;http://localhost:3001&#39;</pre><pre>export const fetchWorkouts = () =&gt; {<br>  let data = {<br>    method: &#39;GET&#39;,<br>    headers: {<br>      &#39;Accept&#39;: &#39;application/json&#39;,<br>      &#39;Content-type&#39;: &#39;application/json&#39;<br>    }<br>  }</pre><pre>  return dispatch =&gt; {<br>    fetch(`${apiURL}/resources`, data)<br>      .then(response =&gt; response.json())<br>      .then(resources =&gt; dispatch({<br>          type: &#39;FETCH_RESOURCES&#39;,<br>          resources<br>      }))<br>      .catch(errors =&gt; errors)<br>  }<br>}</pre><p>A few things to note here. First, this is a React/Redux “API call action”. It uses ‘Redux-Thunk’ to handle the fetch request, but the same principles apply to use other tools like ‘Axios’ or vanilla fetch requests.</p><p>Second, note that here we have an apiURL variable that points to the Rails server. The variable is then interpolated into the fetch request address where it’s used to call on the “resources” endpoint. Although this is the correct way to handle these calls on your development environment, this wouldn’t work for a production build when deployed to Heroku. This is because we are “hard-coding” the path to our server, and Heroku –after deployment and once the app has been built on their server, uses its own HTTP routing stack with unique paths to the app’s Heroku server.</p><p>To fix this, you simply remove the apiUrl variable from the fetch request path and leave your resource endpoint. Something along:</p><pre>//const apiURL = &#39;http://localhost:3001&#39;</pre><pre>export const fetchWorkouts = () =&gt; {<br>  let data = {<br>    method: &#39;GET&#39;,<br>    headers: {<br>      &#39;Accept&#39;: &#39;application/json&#39;,<br>      &#39;Content-type&#39;: &#39;application/json&#39;<br>    }<br>  }</pre><pre>  return dispatch =&gt; {<br>    fetch(`/resources`, data) //removed hard-coded path<br>      .then(response =&gt; response.json())<br>      .then(resources =&gt; dispatch({<br>          type: &#39;FETCH_RESOURCES&#39;,<br>          resources<br>      }))<br>      .catch(errors =&gt; errors)<br>  }<br>}</pre><p>One last thing to consider, is the use of ‘React-Router’.</p><p>If your React client uses ‘react-router’ for its routing, you would need to make some changes to the Rails backend. Specifically, you will need to create a ‘fallback route’ for all routes or paths that don’t match or are not included in your client’s routes. In other words, you will tell your app to serve the client’s index.html for any path that is not included in your client’s routes.</p><p>To do so, in the Rails app/application_controller.rb file, add the following:</p><pre>class ApplicationController &lt; ActionController::API</pre><pre>  def fallback_index_html<br>    render :file =&gt; &#39;public/index.html&#39;<br>  end<br>  <br>end</pre><p>And in the Rails config/routes.rb file, add the following:</p><pre>get &#39;*path&#39;, to: &quot;application#fallback_index_html&quot;, constraints: -&gt;(request) do<br>    !request.xhr? &amp;&amp; request.format.html?<br>  end</pre><p>All right, that was a lot to do! But now our application is ready to be deployed. Next, we’ll create the Heroku app and deploy our Rails with React app to it.</p><p>This will be a good time to commit your work.</p><h4><strong>Deploying to Heroku</strong></h4><p>As a reminder, I’m assuming you have a Heroku account and have the Heroku CLI installed. If you haven’t, please go to <a href="https://www.heroku.com/,">https://www.heroku.com/,</a> create an account and follow instructions on how to set up the CLI.</p><p>The first thing to do is to log in to your Heroku account. In your terminal, execute heroku login and fill in your credentials.</p><p>Now, create a new Heroku app:</p><p>In your terminal, and in your app’s root directory, execute the following: heroku create your-app-name</p><p>You can confirm the new Heroku app is connected to your Rails + React app by executing git remote –v. This will list all your remote depositories associated with your app directory. You should see Heroku listed there because Heroku uses your git repo to build your app on their server.</p><p>Next, you will tell Heroku how to build the app. Since the app uses Node.js and Ruby on the stack, Heroku needs to execute the correct buildpacks when building the app. To do so, execute the following in your terminal:</p><p>heroku buildpacks:add heroku/nodejs --index 1</p><p>heroku buildpacks:add heroku/ruby --index 2</p><p>You are all set!!</p><p>Commit all your changes and push them to Heroku:</p><p>git add .</p><p>git commit -m &quot;first Heroku deploy &quot;</p><p>git push heroku master</p><p><em>Note: the </em>git push<em> command takes in two arguments, a remote name and the local branch name to be pushed, i.e </em>git push &lt;remotename&gt; &lt;branchname&gt;<em>. You should push the branch name where all these changes took place. If you followed my suggestion to create a new deployment branch before making these changes, you will need to deploy that branch instead of </em>master<em> above.</em></p><p><em>When you push your app to Heroku, Heroku will run the scripts we set in the Rails </em><em>package.json file to build the app. This process will take a minute or two. You can see the </em><em>build and </em><em>deploy scripts running in the background while this process takes place.</em></p><p>You probably have some .env variables in your development. Since these variables are usually protected and not committed to git, Heroku won’t know about them when we push the project to its master branch. To add these variable to your Heroku project, we can run the following command in the terminal AFTER the application has been created and uploaded to Heroku:</p><pre>heroku config:set VARIABLE=VALUE</pre><p>And finally!… since this is a brand new app hosted in Heroku, there won’t be a database set yet. You must create it, migrate it, and seed it (if you have a seed file). In your terminal:</p><p>heroku rake db:create</p><p>heroku rake db:migrate</p><p>heroku rake db:seed</p><p><strong>And that’s it! You should now have a working production app hosted in Heroku.</strong></p><p>You can open and test the app by running heroku open on the root directory.</p><p>One final note: if you find that your app’s images or styling aren’t loading properly, it may be because their corresponding static assets aren’t being processed while deploying. Check the Heroku logs to see which assets aren’t loading.</p><p>The quick fix is to pre-compile your assets before deployment. Note, however, that doing the following will slow down the app’s loading time. It’s recommended instead that you host the static assets on a CDN service.</p><p>To pre-compile assets, change the following lines in the Rails config/environments/production.rb file:</p><p>config.assets.complie = true</p><p>config.serve_static_assests = true</p><p>If you are new to deployment, I hope this guide has saved you a few hours of research and has allowed you to successfully deploy your app. If you are experienced, hopefully, you can use this guide as a refresher and maybe keep it as a comprehensive reference for the future. I sure will.</p><p><strong>References:</strong></p><p><a href="https://devcenter.heroku.com/articles/getting-started-with-rails5">https://devcenter.heroku.com/articles/getting-started-with-rails5</a></p><p><a href="https://medium.com/@bruno_boehm/reactjs-ruby-on-rails-api-heroku-app-2645c93f0814">https://medium.com/@bruno_boehm/reactjs-ruby-on-rails-api-heroku-app-2645c93f0814</a></p><p><a href="https://www.youtube.com/watch?v=Z0sFlwz0YvU">https://www.youtube.com/watch?v=Z0sFlwz0YvU</a></p><p><a href="https://medium.com/@pjbelo/setting-up-rails-5-2-active-storage-using-google-cloud-storage-and-heroku-23df91e830f8">https://medium.com/@pjbelo/setting-up-rails-5-2-active-storage-using-google-cloud-storage-and-heroku-23df91e830f8</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=43d7469e122e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/how-i-get-it/rails-react-js-heroku-deployment-43d7469e122e">Rails + React.js Heroku Deployment</a> was originally published in <a href="https://medium.com/how-i-get-it">How I Get It…</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[JavaScript Execution Context]]></title>
            <link>https://medium.com/how-i-get-it/javascript-execution-context-464c59c032f0?source=rss----4bb7a38a151---4</link>
            <guid isPermaLink="false">https://medium.com/p/464c59c032f0</guid>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Alejandro Sabogal]]></dc:creator>
            <pubDate>Fri, 15 Mar 2019 22:48:48 GMT</pubDate>
            <atom:updated>2019-03-15T22:51:48.716Z</atom:updated>
            <content:encoded><![CDATA[<p>Have you been asked this — or a variant of the following question?</p><p>“Given the following code, please write the order in which the logs will appear in the console:”</p><pre>const a = () =&gt; {<br>	b()<br>	console.log(&quot;a&quot;)<br>	<br>};</pre><pre>const b = () =&gt; {<br>	console.log(&quot;b&quot;)<br>	c()<br>};</pre><pre>const c = () =&gt; {<br>	console.log(&quot;c&quot;)<br>};</pre><pre>c()<br>console.log(&quot;d&quot;)<br>a()</pre><p>Can you answer the question?</p><p>There is a fundamental principle in JavaScript that makes answering this question very easily; The Execution Context (and Execution Stack).</p><p>JavaScript is a a single threaded language and therefore, only one task can run at a time. The environment where this task or code is evaluated and executed is referred to as the execution context. In other words, wherever — or whenever a line of code runs in JavaScript, it runs in its execution context.</p><p>To understand how the execution context is created, we must first understand how the JavaScript engines run code in general: Every time JavaScript code runs, the engine does several things. One of them is to read the code line by line and use the syntax parser. In this phase, the engine parses the code and compiles it to instruct the computer on what to do. It also checks for errors in syntax and if there are none, it stores variable and function declarations to memory and creates the execution contexts.</p><p>The two main types of execution contexts in JavaScript are the:</p><ul><li><strong>Global Execution Context</strong>: this is the base execution context and is where EVERYTHING in JavaScript is available. All of the codebase is wrapped inside the global execution environment; variable declarations, variable assignments, function calls, and function declarations for example, all run in the global execution context. In JavaScript “global” means not inside a function and there can only be one global execution context in a particular program.</li><li><strong>Functional Execution Context</strong>: this is the context that exists inside a particular function. Whenever a function is invoked or called, the JavaScript engine creates another execution context that belongs to that function’s environment only. This functional execution cotntext is then stacked on top of the global execution context. All following function calls will generate their own execution context and will be stacked on top of the previous execution context.</li></ul><p>Let’s take a look at the question and the code again to see the execution contexts in our code:</p><pre>///////////////GLOBAL ENVIRONMENT//////////////<br></pre><pre>const a = () =&gt; {<br>  //<em>function a execution context</em><br>  b()              <br>  console.log(&quot;a&quot;) <br>  };<br>  <br>  const b = () =&gt; {<br>   <em>//function b execution context</em><br>   console.log(&quot;b&quot;)<br>   c()         <br>  };<br>  <br>  const c = () =&gt; {<br>  <em> //function c execution context</em><br>   console.log(&quot;c&quot;)  <br>  };<br>  <br>  <em>//global execution context</em><br>  c() <br>  console.log(&quot;d&quot;) <br>  a()<br>  <br>  //////////////GLOBAL ENVIRONMENT///////////////</pre><p>OK, so we’ve determined our execution contexts, but how do we determine the order of our console.logs and answer the question? To do so we need to understand the execution stack.</p><p>When the JavaScript engine parses our code in its first pass, it reads code from top to bottom in the global environment, creates the global execution context and stores it at the bottom of what is known as the execution stack:</p><pre>—EXECUTION STACK—<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///GLOBAL EXECUTION///</pre><p>If there is a function call, the engine creates an execution context for that function and stacks it on top of the execution stack. If it finds another function, it creates another execution context for that function and stacks it on top of the execution stack:</p><pre>—EXECUTION STACK—<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///FUNC 2 EXECUTION///<br>///FUNC 1 EXECUTION///<br>///GLOBAL EXECUTION///</pre><p>This process is repeated until no other function calls are found. The order of the stack is determined by the order in which the engine finds the function calls, and the order of code execution is determined by the order of the execution stack. In the example above, function 2, will be executed first, then function 1, and finally, whatever code is left in the global environment/global execution context will be executed.</p><p>Let’s take a look again at our code in question and stack our execution contexts:</p><pre>///////////////GLOBAL ENVIRONMENT//////////////</pre><pre>const a = () =&gt; {<br>  //<em>function a execution context</em><br>  b()              <br>  console.log(&quot;a&quot;) <br>  };<br>  <br>  const b = () =&gt; {<br>   <em>//function b execution context</em><br>   console.log(&quot;b&quot;)<br>   c()         <br>  };<br>  <br>  const c = () =&gt; {<br>  <em> //function c execution context</em><br>   console.log(&quot;c&quot;)  <br>  };<br>  <br>  <em>//global execution context</em><br>  c() <br>  console.log(&quot;d&quot;) <br>  a()<br>  <br>  //////////////GLOBAL ENVIRONMENT///////////////</pre><p>Our initial stack looks like this:</p><pre>—EXECUTION STACK—<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///FUNC C EXECUTION///<br>///GLOBAL EXECUTION///</pre><p>The engine finds a call to function c, stacks it on top of the stack and executes function c because there are no other functions to call, we only console log “c”. Once the function is called and executed, it gets removed from the stack, and so we are back in the global execution context:</p><pre>—EXECUTION STACK—<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///GLOBAL EXECUTION///</pre><p>The engine now finds console.log(“d”) in the global environment/context. At this point there is nothing to stack because we are still in the global execution context, so no new execution context is created. After the engine logs “d”, it finds a call to function a. At this point an execution context is created for function a and it’s put on top of the stack. Our stack now looks like this:</p><pre>—EXECUTION STACK—<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///FUNC A EXECUTION///<br>///GLOBAL EXECUTION///</pre><p>Now the engine attempts to execute function a but it finds a call to function b inside that context, so it won’t execute function a and instead creates a new execution context for function b and stacks it on top of the execution stack like so:</p><pre>—EXECUTION STACK—<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///FUNC B EXECUTION///<br>///FUNC A EXECUTION///<br>///GLOBAL EXECUTION///</pre><p>Now inside function b’s execution context, the engine logs “b” and it encounters a call to function c which needs to stack at the top of the execution stack. Because this is the last line of code in function b, function b is fully executed and removed from the stack by then. So our execution stack now looks like this:</p><pre>—EXECUTION STACK—<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///FUNC C EXECUTION///<br>///FUNC A EXECUTION///<br>///GLOBAL EXECUTION///</pre><p>Notice that function a is still in the execution stack because it hasn’t been executed yet. Remember the engine first found a call to function b inside function a and that call needed to be executed first. As of now function a is not executed and remains in the execution stack.</p><p>So at this point the next execution in the stack is for function c. The engine logs “c” and function c gets fully executed and removed from the stack, leaving function a at the top of the stack and next in line to be executed:</p><pre>—EXECUTION STACK—<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///////////////////////<br>///FUNC A EXECUTION///<br>///GLOBAL EXECUTION///</pre><p>What remains to be executed in function a is the console.log(“a”). So the engine logs “a” and function a is fully executed. It gets removed from the stack and the engine is left with the global execution only. Since there is nothing else to execute in the global environment, the global execution context gets removed from the stack and all our code is fully executed and complete.</p><p>Our answer then should be:</p><p>c d b c a</p><p>I think this is a very important concept to grasp in JavaScript. It helped me understand the basics of how JavaScript code runs and works. It helped me understand Scope, variable assignment and declaration on ES6, and other important concepts. Hopefully it’s given you a similar understanding that you can use to become a better JavaScript developer.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=464c59c032f0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/how-i-get-it/javascript-execution-context-464c59c032f0">JavaScript Execution Context</a> was originally published in <a href="https://medium.com/how-i-get-it">How I Get It…</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>