{"id":21341816,"url":"https://github.com/biglovisa/creact","last_synced_at":"2025-07-12T15:30:42.427Z","repository":{"id":90170616,"uuid":"47210629","full_name":"biglovisa/creact","owner":"biglovisa","description":"crud in Rails and React | Tutorial","archived":false,"fork":false,"pushed_at":"2017-10-02T22:32:41.000Z","size":162,"stargazers_count":124,"open_issues_count":2,"forks_count":42,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-06-12T18:09:05.381Z","etag":null,"topics":["rails","react","react-rails","tutorial"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/biglovisa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2015-12-01T18:56:55.000Z","updated_at":"2024-01-12T00:07:55.000Z","dependencies_parsed_at":"2023-10-20T18:24:32.968Z","dependency_job_id":null,"html_url":"https://github.com/biglovisa/creact","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/biglovisa%2Fcreact","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/biglovisa%2Fcreact/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/biglovisa%2Fcreact/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/biglovisa%2Fcreact/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/biglovisa","download_url":"https://codeload.github.com/biglovisa/creact/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225824738,"owners_count":17529906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rails","react","react-rails","tutorial"],"created_at":"2024-11-22T00:58:26.539Z","updated_at":"2024-11-22T00:58:27.217Z","avatar_url":"https://github.com/biglovisa.png","language":"Ruby","readme":"# Creact\n## Crud + React\n\nIn this tutorial we are going to clone down a repo with a Rails API and build out a React front end using the [react-rails](https://github.com/reactjs/react-rails) gem. We won't cover the Rails API in detail and it is assumed that you are familiar with the general structure of a Rails project and JavaScript syntax.\n\n### Sections\n\n* [0. Up and running](https://github.com/applegrain/creact/blob/master/README.md#0-up-and-running)\n* [1. What's already here?](https://github.com/applegrain/creact/blob/master/README.md#1-whats-already-here)\n* [2. Adding React to your Rails project](https://github.com/applegrain/creact/blob/master/README.md#2-adding-react-to-your-rails-project)\n* [3. Component Hierarchy](https://github.com/applegrain/creact/blob/master/README.md#3-component-hierarchy)\n* [4. Our first React component](https://github.com/applegrain/creact/blob/master/README.md#4-our-first-react-component)\n* [5. Hello, Creact!](https://github.com/applegrain/creact/blob/master/README.md#5-hello-creact)\n* [6. Rendering all skills](https://github.com/applegrain/creact/blob/master/README.md#6-rendering-all-skills)\n* [7. Add a new skill](https://github.com/applegrain/creact/blob/master/README.md#7-add-a-new-skill)\n* [8. Delete a skill](https://github.com/applegrain/creact/blob/master/README.md#8-delete-a-skill)\n* [9. Edit a skill](https://github.com/applegrain/creact/blob/master/README.md#9-edit-a-skill)\n* [10. Updating the level of a skill](https://github.com/applegrain/creact/blob/master/README.md#10-updating-the-level-of-a-skill)\n* [11. Refactor](https://github.com/applegrain/creact/blob/master/README.md#11-refactor)\n* [12. Filter Skills by Level](https://github.com/applegrain/creact/blob/master/README.md#12-filter-skills-by-level-1)\n* [13. You are awesome](https://github.com/applegrain/creact/blob/master/README.md#13-you-are-awesome)\n\n\u003cbr\u003e\n\n### 0. Up and running\n---\n\nIn your terminal, clone the project:\n\n```\n$ git clone git@github.com:applegrain/creact-starter.git; cd creact-starter\n$ bundle install\n$ rake db:setup\n```\n\nIf you were instead to run `$ rake db:{create,migrate,seed}` you might have trouble and get something like `NoMethodError for details=`. This is because when we manually run the `migrate` command, Rails doesn't know that it needs to reset column information on what was just migrated to account for potentially new columns, so it hiccups trying to call methods on those columns. Conversely, the `setup` command includes a step for resetting columns, so we're in the clear to then call methods.\n\nrun tests with:\n\n\n```\n$ bundle exec rspec\n```\n\nand start the server with:\n\n```\n$ bundle exec rails s\n```\n\n\u003cbr\u003e\n\n### 1. What's already here?\n---\n\nIf you start the server and go to `http://localhost:3000` you'll see an `h1` tag and many skills - each with a name, details and a level set as [enum](http://guides.rubyonrails.org/4_1_release_notes.html#active-record-enums). The seed data doesn't really reflect the fact that it is a skill. Feel free to change the [Faker](https://github.com/stympy/faker) options in `db/seeds.rb`.\n\nIn `config/routes.rb` there is already a root path set up. This will be the only route we are going to use. We also have a `app/controllers/site_controller.rb` with an index action that passes the instance variable `@skills` to the view. In the view, `app/views/site/index.html.erb`, we are iterating over `@skills` to render all the skills on the DOM. Later we are going to delete the instance variable in the action and have an almost empty view.\n\nIn `config/routes.rb` there is also routes for `Api::V1::Skills`. The json API is already built out with the necessary actions. In `app/controllers/api/v1/skills_controller.rb` we are serving json from four endpoints.\n\nFurther resources on building a json API\n\n- [build a json API (code-along)](https://vimeo.com/134915023).\n\n\u003cbr\u003e\n\n### 2. Adding React to your Rails project\n---\n\n[React.js](https://facebook.github.io/react/) is a \"JavaScript library for building user interfaces\". It's a tiny framework used to build your view layer. React can be used in combination with almost any back end, and can be combined with other front end frameworks as well. React, can be sprinkled in\nanywhere in your Rails application. React could be used for a search bar, be part of the nav bar or be used for the whole page.\n\nReact is a JavaScript library but fortunately we can use the [react-rails](https://github.com/reactjs/react-rails) gem that enables us to use React and JSX in our Rails application. You'll get more familiar with JSX a bit further down but it's basically the equivalent to erb. It's how we mix JavaScript with HTML - the same way we can mix Ruby with HTML when we use erb.\n\n\u003cbr\u003e\n\nAdd `gem 'react-rails'` to your Gemfile.\n\n\u003cbr\u003e\n\n```\n$ bundle\n$ rails g react:install\n```\n\nThe last command generated a file, created a directory and inserted three lines to our code.\n\n\u003cbr\u003e\n\n```\n\n$ rails g react:install\n    create  app/assets/javascripts/components\n    create  app/assets/javascripts/components/.gitkeep\n    insert  app/assets/javascripts/application.js\n    insert  app/assets/javascripts/application.js\n    insert  app/assets/javascripts/application.js\n    create  app/assets/javascripts/components.js\n\n```\n\n\u003cbr\u003e\n\nIf you open up `app/assets/javascripts/application.js` you'll see the three lines React inserted.\n\n\u003cbr\u003e\n\n```\n\n//= require react\n//= require react_ujs\n//= require components\n\n```\n\n\u003cbr\u003e\n\nJust like jQuery, we require `react`, `react_ujs` and `components` to the asset pipeline. In `app/assets/javascripts/components.js` we require the directory `components`. It's in this directory where all our React components will live. Think of a component as a type of class, it represents a \"unit\" of code. We build many small components that we combine to build bigger features.\n\n\u003cbr\u003e\n\n### 3. Component Hierarchy\n---\n\nThe notation for rendering React components is: \u003cComponentName /\u003e.\n\nComponents have parent-child relationships, if component \"Cat\" renders component \"Kitten\", \"Cat\" is the parent of \"Kitten\". As an example, let's build the component hierarchy for a site with a header, a side bar and tweets:\n\nThe main component, `\u003cMain /\u003e`, will render the `\u003cHeader /\u003e` and `\u003cBody /\u003e` component. The `Header` and the `Body` components exist independently of each other but they need to know about similar data, such as the current user or which link in the header was clicked last. We can store that information and keep track of the current state of our application in `Main` and pass it down to `Header` and `Body`. By storing the data in one place we are also only updating the data in one place - we have a so-called \"Single Source of Truth\", one place where data is stored and updated.\n\nIn `\u003cBody /\u003e`, we render `\u003cTweets /\u003e` and `\u003cAds /\u003e`. `\u003cTweets /\u003e` and `\u003cAds /\u003e` don't really depend on the same data but rendering both of them in the `Body` makes sense since they might share styling attributes. Finally, `\u003cTweets /\u003e` renders an entire collection of `\u003cTweet /\u003e`. Each individual tweet is a single `Tweet` component to keep it DRY: \"Don't Repeat Yourself\".\n\n\u003cbr\u003e\n\n```\n\n          Main\n        /      \\\n       /        \\\n    Header       Body\n                /     \\\n             Ads     Tweets\n                          \\______\n                              |   Tweet\n                              |       _\\_\n                              |      /    \\\n                              |  Body   TweetOptionsBars\n                              |\n                              |___\n                              |   Tweet\n                              |       _\\_\n                              |      /    \\\n                              |  Body   TweetOptionsBars\n                              |\n                              etc\n\n```\n\nadditional resources on component hierarchy:\n- [Thinking in React](https://facebook.github.io/react/docs/thinking-in-react.html)\n- [Video](http://tagtree.tv/thinking-in-react) tutorial that walks through the code used in above article\n\n### 4. Our first React component\n---\n\nNow we need to connect our Rails views to our (yet non-existent) React code. First, add a file to the components directory. This will be our main file.\n\n\u003cbr\u003e\n\n```\n$ touch app/assets/javascripts/components/_main.js.jsx\n```\n\n\u003cbr\u003e\n\nThe `.js.jsx` extension is similar to `html.erb`. In Rails views, we write erb that gets compiled down to HTML. With `js.jsx` files, we write JSX that gets compiled to JavaScript.\n\nThen we establish a connection between the Rails view and the main component. To render `_main.js.jsx` in our root we need to add the view helper we get from the react-rails gem. It puts a div on the page with the requested component class. Go ahead and delete the old code in the view. Since we use React as our view layer, our Rails views are next to empty (as they should be).\n\n\u003cbr\u003e\n\nSince the Rails asset pipeline will take all of our JavaScript and mash it together, the names of the JavaScript files don't really matter. Below, React will look for a component that's named `Main`.\n\n**app/views/site/index.html.erb**\n```\n\n\u003c%= react_component 'Main' %\u003e\n\n```\n\n\u003cbr\u003e\nAnd let's add our first React component - head to the browser and make sure it works.\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_main.js.jsx**\n```\n\nvar Main = React.createClass({\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003ch1\u003eHello, Creact!\u003c/h1\u003e\n      \u003c/div\u003e\n    )\n  }\n});\n\n```\n\nIf you're receving an error about Rails not recognizing your react_components, be sure to restart your server.\n\n\u003cbr\u003e\n\n### 5. Hello, Creact!\n---\n\nWe did it! We have copy-pasted our first component and our Rails view is empty. Let's take a closer look at `Main`.\n\nWe have built a component and given it a name. It has only one function, `render()`. When a React component is mounted on the DOM, its `render()` method will execute and also trigger it's children's `render()` methods. The code that's in the `return` statement is the JSX that will render on the page. Right now our HTML looks like regular HTML, but soon we will add in some JavaScript so it becomes more dynamic. Each React component can only return one element, so all JSX elements in the return statement need to be in one wrapper div.\n\n\u003cbr\u003e\n\n*Bad - returning sibling HTML elements that aren't wrapped by a shared parent div.*\n\n```\n\nreturn (\n  \u003cdiv\u003e\n    \u003ch1\u003eHello, Creact!\u003c/h1\u003e\n  \u003c/div\u003e\n  \u003cdiv\u003e\n    \u003cp\u003eAll of the contents\u003c/p\u003e\n  \u003c/div\u003e\n)\n\n```\n\n\u003cbr\u003e\n\n*Better - we have multiple sibling HTML elements which share a parent div.*\n\n```\nreturn (\n  \u003cdiv\u003e\n    \u003cdiv\u003e\n      \u003ch1\u003eHello, Creact!\u003c/h1\u003e\n    \u003c/div\u003e\n    \u003cdiv\u003e\n      \u003cp\u003eAll of the contents\u003c/p\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n)\n```\n\n\u003cbr\u003e\n\nLet's build out the component hierarchy. We are going to implement basic CRUD functionality; **c**reate, **r**ead, **u**pdate, **d**elete. Our `Main` component could render a `Header` and a `Body`. In the `Body`, we need to be able to view all skills, create a new skill, edit a skill and delete a skill. So, `Body` could render `\u003cNewSkill /\u003e` and `\u003cAllSkills /\u003e`. `NewSkill` is a form to create new skills and `AllSkills` renders a collection of individual `Skill` components - each `Skill` component has it's own delete and edit button.\n\n\u003cbr\u003e\n\n```\n\n         Main\n       /      \\\n  Header        Body\n              /     \\\n        NewSkill    AllSkills\n                        \\\n                        Skills * n\n\n```\n\n\u003cbr\u003e\n\nLet's remove our current `h1` and add `\u003cHeader /\u003e` in it's place.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_main.js.jsx**\n```\nvar Main = React.createClass({\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cHeader /\u003e\n      \u003c/div\u003e\n    )\n  }\n});\n```\n\n\u003cbr\u003e\n\nWe are rendering the `Header` component (still non-existent) in the `Main` component, which makes `Header` the child of `Main`.\n\n\u003cbr\u003e\n\n```\n$ touch app/assets/javascripts/components/_header.js.jsx\n```\n\n\u003cbr\u003e\n\nOur code for the `Header` component will look very similar to what we have in `Main`. For now, put an `h1` in the return statement with whatever text you want. Hop over to your browser to make sure the `h1` renders as it should. If not, take a look at the code we first had in `Main` and compare the syntax. Let's leave the `Header` for now and move on to building out the body.\n\n\u003cbr\u003e\n\n### 6. Rendering all skills\n---\n\nNow let's render all skills on the page. First, we need to add a `Body` component in which our `NewSkill` and `AllSkills` components will be rendered.\n\n```\n$ touch app/assets/javascripts/components/_body.js.jsx\n$ touch app/assets/javascripts/components/_all_skills.js.jsx\n$ touch app/assets/javascripts/components/_new_skill.js.jsx\n```\n\nGo ahead and add the code from `Header` in the `Body`, `AllSkills` and `NewSkill` components. `Body` should render `AllSkills`. Put an arbitrary `h1` in `AllSkills` so we can get some feedback on the page. At this point, two `h1`'s should be rendered on the page. If they don't, open up the dev tools (option + cmd + i) and see if you have any errors in the console. If they aren't useful, look over the syntax carefully and make sure it looks like what we have in `Main`.\n\nOur next step is to fetch all skills from the server. We will use Ajax to ping the index action of our Rails API to get all the skills from the database. It's important that our Ajax call is only executed once. It's expensive to make Ajax calls and depending on the scale of your applications, it can cause performance issues. If we were using jQuery, we would implement this in a `$(document).ready()` function.\n\nReact components have some built in methods available that execute during different points during a component's lifecycle. Some examples include functions that execute before/after a component mounts on the DOM and before/after it dismounts. In this case, we want a method that renders once when the component is mounted on the DOM. We are going to use `componentDidMount()` which is called right after the component is mounted. For more details about methods that are available to components and when to use them, check out the [docs](https://facebook.github.io/react/docs/component-specs.html).\n\nLet's add a `componentDidMount()` function and just `console.log()` something so we now it's being called.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\nvar AllSkills = React.createClass({\n  componentDidMount() {\n    console.log('Hello');\n  },\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003ch1\u003eHello from All Skills!\u003c/h1\u003e\n      \u003c/div\u003e\n    )\n  }\n});\n\n```\n\n\u003cbr\u003e\n\nWhy is there a comma at the end of our function? Take a closer look at the syntax. When we write `var AllSkills = React.createClass( /* Code here */ )` we give it an object containing all the code for the component. Since elements in objects are comma separated, we put a comma at the end of our functions.\n\nDid you see the output from the `console.log()` in the browser console? Cool! Let's see if we can fetch all skills.\n\n```\n$.getJSON('/api/v1/skills.json', (response) =\u003e { console.table(response) });\n```\n\nMake sure to look in the browser console to make sure everything looks good.\n\nRight now we are just logging the result to make sure we get the objects we want. Really, what we want to do is to store it on the component so we can use it more easily throughout our application. Data that will change is stored as `state` on the component. In React, state is mutable, so data that will change throughout the program should be stored as state. `getInitialState` is another method we get from React and it's used to  specify the initial values for all the states in the component. Let's create a state called `skills` and set it equal to an empty array.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\nvar AllSkills = React.createClass({\n  getInitialState() {\n    return { skills: [] }\n  },\n\n// rest of the component\n\n```\n\n\u003cbr\u003e\n\nNow, when we get the response back from the server, we want to update `skills` and set it to the value of the skills we got from the server. We want to store it as state because when we add new skills, we want to be able to render them on the page without having to ping the index action of our API again. By using another of React's built in methods, this isn't bad at all.\n\n\u003cbr\u003e\n\n```\n  $.getJSON('/api/v1/skills.json', (response) =\u003e { this.setState({ skills: response }) });\n```\n\n\u003cbr\u003e\n\nTo be sure that we actually updated the state, let's log the state (`console.log(this.state)`) in the `render()` method. Make sure to put it outside of the return statement! You should see something like the following in your browser console.\n\n`this.state.skills` is how we would access the skills array.\n\n\u003cbr\u003e\n\n```\n\u003e Object {skills: Array[0]}\n\u003e Object {skills: Array[50]}\n```\n\n\u003cbr\u003e\n\nWe might eventually want to create a `Skill` component for each object in the skills array. For now, let's just map over the objects in the array and create DOM nodes out of them. Since JSX is just HTML + JS, we can build HTML elements and insert JavaScript wherever we need it, similar to how we can insert Ruby in HTML elements using erb.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\n// componentDidMount() and getInitialState()\n\n  render() {\n    var skills = this.state.skills.map((skill) =\u003e {\n      return (\n        \u003cdiv\u003e\n          \u003ch3\u003e{skill.name}\u003c/h3\u003e\n          \u003cp\u003e\u003cstrong\u003eLevel:\u003c/strong\u003e {skill.level}\u003c/p\u003e\n          \u003cp\u003e{skill.details}\u003c/p\u003e\n        \u003c/div\u003e\n      )\n    });\n\n    return(\n      \u003cdiv\u003e\n        {skills}\n      \u003c/div\u003e\n    )\n  }\n```\n\n\u003cbr\u003e\n\nThe return value from the `this.state.skills.map...` will be an array of HTML divs, each with an `h3` and two `p` tags (if you don't believe me, log the return value and look). As you can see, inserted JavaScript needs to be enclosed in curly braces - the erb equivalent to this would be `\u003c%= some_ruby_here %\u003e`. In the return statement we have replaced the `h1` tag with the skills array we built above. In the return statement we write JSX and our skills array is JavaScript, so in order for it to be evaluated it needs to be wrapped in curly braces. Head over to the browser and make sure it all works ok!\n\nYou should see an error like this in the browser console:\n\n\u003cbr\u003e\n\n```\nEach child in an array or iterator should have a unique \"key\" prop. Check the render method of `AllSkills`. See https://fb.me/react-warning-keys for more information.\n```\n\n\u003cbr\u003e\n\nA key prop?\n\nWhen we are rendering multiple similar HTML elements - in our case, 50 of the same type - we need to supply each with a unique key. React uses a diffing algorithm to figure out which parts of your application has changed and needs to be re-rendered. This is partially what makes React so fast and snappy in the browser. It uses the keys to identify the DOM nodes and if we have several on the same kind, the diffing algorithm doesn't work as it should. For more details on this topic, check out the [docs](https://facebook.github.io/react/docs/reconciliation.html).\n\nLet's help React out and add a key prop.\n\n\u003cbr\u003e\n\n```\nvar skills = this.state.skills.map((skill) =\u003e {\n  return (\n    \u003cdiv key={skill.id}\u003e\n      \u003ch3\u003e{skill.name}\u003c/h3\u003e\n      \u003cp\u003e\u003cstrong\u003eLevel:\u003c/strong\u003e {skill.level}\u003c/p\u003e\n      \u003cp\u003e{skill.details}\u003c/p\u003e\n    \u003c/div\u003e\n  )\n});\n\n```\n\n\u003cbr\u003e\n\nWe can use each skill's id as a unique key. Refresh, and voila - no more errors.\n\n\u003cbr\u003e\n\n### 7. Add a new skill\n---\n\nRemember the `NewSkill` component?\n\n**app/assets/javascripts/components/_new_skill.js.jsx**\n```\nvar NewSkill = React.createClass({\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003ch1\u003enew skill\u003c/h1\u003e\n      \u003c/div\u003e\n    )\n  }\n});\n\n```\n\n\u003cbr\u003e\n\nWhat do we need to create a new skill? We need a form where the user can enter a name and details and a submit button which will take the input from the form and send it over to the API and add the skill to the database. Let's start with the form. We are just going to use regular HTML to get the form and the submit button on the page.\n\nWhen we are submitting this new skill, we need to grab the text contents of the two input fields, the `name` and the `details`, and store it in our database. In the earlier days of React, we could have used [refs](https://facebook.github.io/react/docs/refs-and-the-dom.html), but nowadays it's more common to use an `onChange` handler and store the text on state. As you can see below, in the `onChange` handlers we are executing an anonymous function which takes an `event` object as its argument, and then sets the state of `name` or `details` to the current text value.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_new_skill.js.jsx**\n```\ngetInitialState() {\n  return { name: '', details: '' }\n},\n\nreturn (\n  \u003cdiv\u003e\n    \u003cinput onChange={ (e) =\u003e this.setState({ name: e.target.value }) } placeholder='Enter name of skill' /\u003e\n    \u003cinput onChange={ (e) =\u003e this.setState({ details: e.target.value }) } placeholder='Details' /\u003e\n    \u003cbutton\u003eSubmit\u003c/button\u003e\n  \u003c/div\u003e\n)\n```\n\n\u003cbr\u003e\n\nCool cool cool - but what happens when the user has entered a new skill and hits submit? Nothing. Let's add an event listener.\n\n\u003cbr\u003e\n\n```\n\u003cbutton onClick={this.handleClick}\u003eSubmit\u003c/button\u003e\n```\n\n\u003cbr\u003e\n\n`onClick` is a React event listener, take a look at the [docs](https://facebook.github.io/react/docs/events.html) to learn more about React events. We give the event listener some JavaScript code to evaluate whenever we click the button. Here, we are telling it to go execute the `handleClick` function - which we haven't written yet.\n\n\u003cbr\u003e\n\n```\n// var NewSkill = ...\n\nhandleClick() {\n  console.log('in handle click!')\n},\n\n// render()....\n\n```\n\n\u003cbr\u003e\n\nCheck in the browser if it works and... great! Now, we need to fetch the form values and send it over to the server to create a new skill. Let's log the form values to be sure we have access to them.\n\n\u003cbr\u003e\n\n```\nvar name    = this.state.name;\nvar details = this.state.details;\nconsole.log(name, details);\n```\n\n\u003cbr\u003e\n\nLet's send the form values over to the server so we can create a new skill.\n\n\u003cbr\u003e\n\n```\nhandleClick() {\n  var name    = this.state.name;\n  var details = this.state.details;\n\n  $.ajax({\n    url: '/api/v1/skills',\n    type: 'POST',\n    data: { skill: { name: name, details: details } },\n    success: (response) =\u003e {\n      console.log('it worked!', response);\n    }\n  });\n},\n\n```\n\n\u003cbr\u003e\n\nWe are making a POST request to '/api/v1/skills' and if it's successful we log the response. Did it work? Create a new skill in the browser and check the browser console. Refresh the page to make sure your newly created skill is rendered on the page.\n\nBut we don't want to refresh the page to see our new skills. We can do better.\n\nWe store all the skills we get from the server as state in `AllSkills`. When we add a new skill, we could add it to the skills array so it will get rendered immediately with the other skills. `AllSkills` needs to have access to the skills array and `NewSkill` wants to update that array. Both children of `Body` need access to the skills array so we should store it as state in `Body` and give both children access to it.\n\nLet's move some code around. Move `getInitialState()` and `componentDidMount()` from `AllSkills` to `Body`. Now, we fetch the skills when `Body` is mounted on the DOM and we store them as state on the `Body` component.\n\nHow does `AllSkills` get access to all the skills?\n\nParents can send variables down to their children as `props`. `Props` are immutable in the child. Let's send the skills array from the `Body` component to the `AllSkills` component as props.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_body.js.jsx**\n```\n\u003cAllSkills skills={this.state.skills} /\u003e\n```\n\n\u003cbr\u003e\n\nWe have one more change to do before the skills will render on the DOM. In `AllSkills` we are iterating over `this.state.skills` to create DOM elements but we no longer have that state stored on the component. `AllSkills` receives the skills as props from the parent, so instead of `this.state.skills` we need to ask for `this.props.skills`.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\nvar skills = this.props.skills.map((skill) =\u003e {\n  return (\n    \u003cdiv key={skill.id}\u003e\n      \u003ch3\u003e{skill.name}\u003c/h3\u003e\n      \u003cp\u003e\u003cstrong\u003eLevel:\u003c/strong\u003e {skill.level}\u003c/p\u003e\n      \u003cp\u003e{skill.details}\u003c/p\u003e\n    \u003c/div\u003e\n  )\n});\n\n```\n\n\u003cbr\u003e\n\nLike we can pass down values from parents to children, we can also pass function references that can be executed in the child.\n\nLet's starts from the `Body`. We want to build a function that's called `handleSubmit()` that will add the new skill to the skills array.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_body.js.jsx**\n```\n// getInitialState() and componentDidMount()\n\nhandleSubmit(skill) {\n  console.log(skill);\n},\n\n// renders the AllSkills and NewSkill component\n\n```\n\n\u003cbr\u003e\n\nThen, we want to send a reference to this function down to the `NewSkill` component.\n\n\u003cbr\u003e\n\n```\n\u003cNewSkill handleSubmit={this.handleSubmit} /\u003e\n```\n\n\u003cbr\u003e\n\nIn the `NewSkill` component, we can call this function by adding parenthesis, just like a regular JavaScript function. In the `success` function, execute the `handleSubmit` function and give it the name and details as an object as an argument.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_new_skill.js.jsx**\n```\n$.ajax({\n  url: '/api/v1/skills',\n  type: 'POST',\n  data: { skill: { name: name, details: details } },\n  success: (skill) =\u003e {\n    this.props.handleSubmit(skill);\n  }\n});\n```\n\n\u003cbr\u003e\n\nCheck your browser console to see if you get any output from `handleSubmit` in the `Body` component.\n\nAlmost there!\n\nNow we need to add it to `this.state.skills`. We can use `concat()` to add the skill to the old state and then set the state with the new state.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_body.js.jsx**\n```\nhandleSubmit(skill) {\n  var newState = this.state.skills.concat(skill);\n  this.setState({ skills: newState })\n},\n```\n\n\u003cbr\u003e\n\nThat's it! We have successfully added a new skill that is rendered on the DOM immediately.\n\nHere is the code for `Body`, `AllSkills` and `NewSkill` in case you want to check your code.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_body.js.jsx**\n```\nvar Body = React.createClass({\n  getInitialState() {\n    return { skills: [] }\n  },\n\n  componentDidMount() {\n    $.getJSON('/api/v1/skills.json', (response) =\u003e { this.setState({ skills: response }) });\n  },\n\n  handleSubmit(skill) {\n    var newState = this.state.skills.concat(skill);\n    this.setState({ skills: newState })\n  },\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cNewSkill handleSubmit={this.handleSubmit} /\u003e\n        \u003cAllSkills skills={this.state.skills} /\u003e\n      \u003c/div\u003e\n    )\n  }\n});\n\n```\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\nvar AllSkills = React.createClass({\n  render() {\n    var skills = this.props.skills.map((skill) =\u003e {\n      return (\n        \u003cdiv key={skill.id}\u003e\n          \u003ch3\u003e{skill.name}\u003c/h3\u003e\n          \u003cp\u003e\u003cstrong\u003eLevel:\u003c/strong\u003e {skill.level}\u003c/p\u003e\n          \u003cp\u003e{skill.details}\u003c/p\u003e\n        \u003c/div\u003e\n      )\n    });\n\n    return (\n      \u003cdiv\u003e\n        {skills}\n      \u003c/div\u003e\n    )\n  }\n});\n\n```\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_new_skill.js.jsx**\n```\nvar NewSkill = React.createClass({\n  handleClick() {\n    var name    = this.state.name;\n    var details = this.state.details;\n\n    $.ajax({\n      url: '/api/v1/skills',\n      type: 'POST',\n      data: { skill: { name: name, details: details } },\n      success: (skill) =\u003e {\n        this.props.handleSubmit(skill);\n      }\n    });\n  },\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cinput onChange={ (e) =\u003e this.setState({ name: e.target.value }) } placeholder='Enter name of skill' /\u003e\n        \u003cinput onChange={ (e) =\u003e this.setState({ details: e.target.value }) } placeholder='Details' /\u003e\n        \u003cbutton onClick={this.handleClick}\u003eSubmit\u003c/button\u003e\n      \u003c/div\u003e\n    )\n  }\n});\n\n```\n\n\u003cbr\u003e\n\n### 8. Delete a skill\n---\n\nOk, we can render skills and add new ones. Let's implement deleting skills so we can get rid of all the test skills we have added.\n\nWhat do we need to do?\n\n1. Add a delete button to each skill\n2. Create a click event for the delete button that will travel up to `Body`\n3. Remove the the skill from the skills array\n4. Update the state in `Body` with the new skills array\n5. Make an Ajax call to our server to remove it from the database\n\nLet's start with adding a delete button to each skill with an on click listener that takes us to the function `handleDelete` in the same component.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\nvar AllSkills = React.createClass({\n  handleDelete() {\n    console.log('in delete skill');\n  },\n\n  render() {\n    var skills = this.props.skills.map((skill) =\u003e {\n      return (\n        \u003cdiv key={skill.id}\u003e\n          \u003ch3\u003e{skill.name}\u003c/h3\u003e\n          \u003cp\u003e\u003cstrong\u003eLevel:\u003c/strong\u003e {skill.level}\u003c/p\u003e\n          \u003cp\u003e{skill.details}\u003c/p\u003e\n          \u003cbutton onClick={this.handleDelete}\u003eDelete\u003c/button\u003e\n        \u003c/div\u003e\n      )\n    });\n\n    return (\n      \u003cdiv\u003e\n        {skills}\n      \u003c/div\u003e\n    )\n  }\n});\n```\n\u003cbr\u003e\n\nDoes it log to the browser console? Cool, we are good to go. Earlier I said that we were going to add a `Skill` component for each skill, but we aren't feeling any obvious pains from this setup, so let's keep it like it is.\n\nThe component needs to communicate with the parent and tell it to delete the idea that was clicked. Like we passed down a function `ref`erence to `NewSkill`, we are going to pass down a function reference that the child can execute when we click the `delete` button.\n\n\u003cbr\u003e\n\n\n**app/assets/javascripts/components/_body.js.jsx**\n```\n// getInitialState() and componentDidMount()\n\nhandleDelete() {\n  console.log('in handle delete');\n},\n\n// render \u003cNewSkill /\u003e\n\n\u003cAllSkills skills={this.state.skills} handleDelete={this.handleDelete} /\u003e\n```\n\n\u003cbr\u003e\n\nGreat! Now, we need to execute the function in the child when we hit the `handleDelete()`.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\nvar AllSkills = React.createClass({\n  handleDelete() {\n    this.props.handleDelete();\n  },\n\n// render() ...\n\n```\n\n\u003cbr\u003e\n\nWe have one pretty obvious problem to solve before we continue. How does the program know *which* skill it is that we want to delete? In the `Body` component we need to use some data that identifies the skill we want to remove so we can filter it out from the skills array. How about an id?\n\nIf we use the skill id and pass it as an argument to `this.props.handleDelete()` we can easily filter the correct skill out by filtering out the skill with a matching id.\n\nLet's use our friend `bind()` - the first argument in `bind()` is the value to be passed as the `this` value when the function is executed and consecutive arguments will be passed to the bound function as arguments.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\nhandleDelete(id) {\n  this.props.handleDelete(id);\n},\n\n// iterate over the skills and create HTML elements\n\n \u003cbutton onClick={this.handleDelete.bind(this, skill.id)}\u003eDelete\u003c/button\u003e\n\n// render() etc\n\n```\n\n\u003cbr\u003e\n\nNow, in `handleDelete()` in the `Body` component we need to use the id passed up from the `AllSkills` component and remove the skill from the database using an Ajax call.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_body.js.jsx**\n```\nhandleDelete(id) {\n  $.ajax({\n    url: `/api/v1/skills/${id}`,\n    type: 'DELETE',\n    success(response) {\n      console.log('successfully removed skill', response)\n    }\n  });\n},\n```\n\n\u003cbr\u003e\n\nClick `delete` and check in the console if it worked - you are awesome!\n\nBut... unless we refresh the page, the skill is still there. We aren't communicating to our view that the skill should be deleted.\n\nLet's add a callback in the `success()` function that removes the skill from the DOM.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_body.js.jsx**\n```\nhandleDelete(id) {\n  $.ajax({\n    url: `/api/v1/skills/${id}`,\n    type: 'DELETE',\n    success: () =\u003e {\n      this.removeSkillFromDOM(id);\n    }\n  });\n},\n\nremoveSkillFromDOM(id) {\n  var newSkills = this.state.skills.filter((skill) =\u003e {\n    return skill.id != id;\n  });\n\n  this.setState({ skills: newSkills });\n},\n```\n\n\u003cbr\u003e\n\nHop over to the browser and remove some skills... this is fantastic.\n\n\u003cbr\u003e\n\n### 9. Edit a skill\n\nThe last and final crud functionality. We are rendering all skills on the page, we are creating new ones, we are deleting them and now we just need to be able to edit them.\n\n\nThis is what we need to accomplish:\n\n1. Add an `Edit` button\n2. Add a click listener for the `Edit` button\n3. On click `Edit`, transform the text fields to input fields (alternatively render a new form below)\n4. When the user clicks the `Submit` button, grab the values from the input fields\n5. Send the updated values over to our Rails API to update the skill\n6. Update the skill and replace the old values with the new values\n\nLet's start with `1` and `2`. Add an `Edit` button and add a click listener for it which takes us to a `handleEdit` function in the same component.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\n// handleDelete()\n\nhandleEdit() {\n  console.log('you are in edit!');\n},\n\n// render() and rest of the skill template\n\n\u003cbutton onClick={this.handleEdit}\u003eEdit\u003c/button\u003e\n```\n\n\u003cbr\u003e\n\nDo you get feedback in your browser console when we click `Edit`? Cool.\n\nWhat needs to happen in `handleEdit()`? For the specific skill that the user asked to edit, add an edit form and var the user edit the values and then submit. If we were using jQuery, we could have just used jQuery's `$.append()` function. However, as this StackOverflow succinctly puts it, it's not a [React way](http://stackoverflow.com/questions/31823801/how-to-append-and-prepend-element-in-react-js-like-jquery). We should render components conditionally based on our state and props.\n\nSo if each skill needs to know whether or not its `Edit` button has been clicked (information which we should store as state), this seems like a good time to refactor out our current skill template in `AllSkills` to its own component.\n\n\u003cbr\u003e\n\n```\n$ touch app/assets/javascripts/components/_skill.js.jsx\n```\n\n\u003cbr\u003e\n\nWe need to update `AllSkills` and create `Skill` components when we iterate over the `this.props.skills`. Notice that we need to send the skill, and references to `handleDelete()` and `handleEdit()` as props to `Skill`. This way we can access these values in `Skill` using the `this.props.*` notation.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\nrender () {\n  var skills = this.props.skills.map((skill) =\u003e {\n    return (\n      \u003cdiv key={skill.id}\u003e\n        \u003cSkill skill={skill}\n               handleDelete={this.handleDelete.bind(this, skill.id)}\n               handleEdit={this.handleEdit}/\u003e\n      \u003c/div\u003e\n    )\n  });\n\n  // return () the skills array\n}\n```\n\n\u003cbr\u003e\n\nIn `Skill` we just return the entire template we removed from `AllSkills`. Notice how we changed the JSX to comply with our new setup.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_skill.js.jsx**\n```\nvar Skill = React.createClass({\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003ch3\u003e{this.props.skill.name}\u003c/h3\u003e\n        \u003cp\u003e\u003cstrong\u003eLevel:\u003c/strong\u003e {this.props.skill.level}\u003c/p\u003e\n        \u003cp\u003e{this.props.skill.details}\u003c/p\u003e\n\n        \u003cbutton onClick={this.props.handleDelete}\u003e\n          Delete\n        \u003c/button\u003e\n\n        \u003cbutton onClick={this.props.handleEdit}\u003eEdit\u003c/button\u003e\n      \u003c/div\u003e\n    )\n  }\n});\n```\n\n\u003cbr\u003e\n\nJust to double check that we have wired things up correctly, go to the browser and make sure you can still delete skills and that something logs to the console when you click `Edit`.\n\nNow, when we click `Edit`, we want to set a state that will tell us that we are editing the skill. Change the click listener for the `Edit` button so we land in a handler function in the current component,\n\n\u003cbr\u003e\n\n```\n\u003cbutton onClick={this.handleEdit}\u003eEdit\u003c/button\u003e\n```\n\n\u003cbr\u003e\n\nand add that function in the `Skill` component.\n\n\u003cbr\u003e\n\n```\nhandleEdit() {\n  // something should happen here\n},\n\n```\n\n\u003cbr\u003e\n\nNow what? Add an initial state to the `Skill` component that defaults to `false`. In `handleEdit()` we need to set this state to true.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_skill.js.jsx**\n```\nvar Skill = React.createClass({\n  getInitialState() {\n    return { editable: false }\n  },\n\n  handleEdit() {\n    this.setState({ editable: true })\n  },\n\n\n  // render() etc..\n```\n\n\u003cbr\u003e\n\nAnd now what? We need to render the component conditionally based on our state. If `this.state.editable` is false, we want to render `h3` tag with the name and the `p` tag with the details as normal. If not, we want to render an input field for the name and a textarea for the details. Sounds like we need ternary operator.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_skill.js.jsx**\n```\n// getInitialState() and handleEdit()...\n\nrender() {\n  var name = this.state.editable ? \u003cinput type='text' defaultValue={this.props.skill.name} /\u003e\n                                 : \u003ch3\u003e{this.props.skill.name}\u003c/h3\u003e\n\n  var details = this.state.editable ? \u003ctextarea type='text' defaultValue={this.props.skill.details}\u003e\u003c/textarea\u003e\n                                    : \u003cp\u003e{this.props.skill.details}\u003c/p\u003e\n  return (\n    \u003cdiv\u003e\n      {name}\n\n      \u003cp\u003e\u003cstrong\u003eLevel:\u003c/strong\u003e {this.props.skill.level}\u003c/p\u003e\n      {details}\n\n      \u003cbutton onClick={this.props.handleDelete}\u003e\n        Delete\n      \u003c/button\u003e\n\n      \u003cbutton onClick={this.handleEdit}\u003eEdit\u003c/button\u003e\n    \u003c/div\u003e\n  )\n}\n});\n```\n\n\u003cbr\u003e\n\nIn the render function we are using a ternary to decide how we should render name/details. It doesn't matter what data we give our component, based on its state, props and the constraints we set up, we always know what the component will render. We want dumb child components that just render conditionally based on the props they receive and their current state. Head over to the browser and check it out!\n\nLet's transform the `Edit` button to a `Submit` button when we click `Edit`. We can use the `editable` state and a ternary directly in the JSX to change that.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_skill.js.jsx**\n```\n\u003cbutton onClick={this.handleEdit}\u003e{this.state.editable ? 'Submit' : 'Edit' }\u003c/button\u003e\n```\n\n\u003cbr\u003e\n\nAwesome.\n\nWe can make a small change to how we update the state in `handleEdit()` to make it toggle between true/false.\n\n\u003cbr\u003e\n\n```\nhandleEdit() {\n  this.setState({ editable: !this.state.editable })\n},\n```\n\n\u003cbr\u003e\n\nBut now, when we click `Submit`, we need to fetch the updated values and send them over to the server to update the given skill. We can do this using the same strategy we deployed in `_new_skill.js.jsx`. Let's add the `onChange` callback to the input field and the textarea in `Skill` (forgot to carry those over when we extracted the skill to its own component).\n\n\u003cbr\u003e\n\n```\ngetInitialState() {\n  return { name: '', details: '' }\n},\n\n....\n\nvar name = this.state.editable ? \u003cinput type='text'\n                                        onChange={ (e) =\u003e this.setState({ name: e.target.value }) }\n                                        defaultValue={this.props.skill.name} /\u003e\n                               : \u003ch3\u003e{this.props.skill.name}\u003c/h3\u003e\n\nvar details = this.state.editable ? \u003ctextarea type='text'\n                                              onChange={ (e) =\u003e this.setState({ details: e.target.value }) }\n                                              defaultValue={this.props.skill.details}\u003e\n                                    \u003c/textarea\u003e\n                                  : \u003cp\u003e{this.props.skill.details}\u003c/p\u003e\n```\n\n\u003cbr\u003e\n\nThere are no strict rules on how you choose to format ternaries. The most important thing is to make it readable for future you and other developers.\n\nLet's add some code to `handleEdit()`.\n\n\u003cbr\u003e\n\n```\nif (this.state.editable) {\n  var name    = this.state.name;\n  var details = this.state.details;\n  console.log('in handleEdit', this.state.editable, name, details);\n  this.onUpdate();\n}\n\nthis.setState({ editable: !this.state.editable })\n```\n\n\u003cbr\u003e\n\nWhat are we trying to find out here? When we hit this function and `this.state.editable` is true, meaning if we are currently editing the text, we want to grab the name and the details and log them to the browser console. Then, we simply toggle the state to alternate between true/false. Try it out in the browser and make sure it's behaving as expected.\n\nCool. Let's walk up the chain, from `Skill` to `AllSkills` to `Body` and update the specific skill in the `Body` component. Why update the skill in the `Body` component and not  right away in the `Skill` component? Because we store all skills as state in the `Body` component and data should be updated in one place.\n\nFetch the values, compose a skill object and trigger the chain by executing the `handleUpdate()` function reference passed down by the parent.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_skill.js.jsx**\n```\nonUpdate() {\n  if (this.state.editable) {\n    var name    = this.state.name;\n    var details = this.state.details;\n    var skill = { name: name, details: details }\n\n    this.props.handleUpdate(skill);\n  }\n  this.setState({ editable: !this.state.editable })\n},\n```\n\n\u003cbr\u003e\n\nThis component is just passing it up to its parent.\n\n\u003cbr\u003e\n\n\n**app/assets/javascripts/components/_all_skills.js.jsx**\n```\nonUpdate(skill) {\n  this.props.handleUpdate(skill);\n},\n\nrender() {\n  var skills = this.props.skills.map((skill) =\u003e {\n    return (\n      \u003cdiv key={skill.id}\u003e\n        \u003cSkill skill={skill}\n               handleDelete={this.handleDelete.bind(this, skill.id)}\n               handleUpdate={this.onUpdate}/\u003e\n      \u003c/div\u003e\n    )\n  });\n```\n\n\u003cbr\u003e\n\nThis is the end of the chain and where we use the `skill` object passed up to update the state, `this.state.skills`.\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_body.js.jsx**\n```\nhandleUpdate(skill) {\n  console.log(skill, 'in handleUpdate');\n},\n\nrender() {\n  return (\n    \u003cdiv\u003e\n      \u003cNewSkill handleSubmit={this.handleSubmit} /\u003e\n      \u003cAllSkills skills={this.state.skills}\n                 handleDelete={this.handleDelete}\n                 handleUpdate={this.handleUpdate} /\u003e\n    \u003c/div\u003e\n  )\n}\n```\n\n\u003cbr\u003e\n\nSince `this.state.skills` is an array of objects it makes most sense to just swap out entire objects instead of opening one up and updating single properties on that object. Let's update the object we pass up from `Skill` to look more like the objects we store as state in `Body`.\n\n\u003cbr\u003e\n\n```\nvar id      = this.props.skill.id;\nvar name    = this.state.name;\nvar details = this.state.details;\nvar level   = this.props.skill.level;\n\nvar skill = {id: id, name: name, details: details, level: level }\n```\n\n\u003cbr\u003e\n\nIn `handleUpdate()` in the `Body` component we need to swap out the old object with the new one - and make an Ajax call to update the database.\n\n\u003cbr\u003e\n\n```\nhandleUpdate(skill) {\n  $.ajax({\n    url: `/api/v1/skills/${skill.id}`,\n    type: 'PUT',\n    data: { skill: skill },\n    success: () =\u003e {\n      console.log('you did it');\n      this.updateSkills(skill);\n      // callback to swap objects\n    }\n  });\n},\n```\n\n\u003cbr\u003e\n\nAnd now let's write the callback that will swap out the objects.\n\n\u003cbr\u003e\n\n```\nhandleUpdate(skill) {\n    // ajax stuffs\n    success: () =\u003e {\n      this.updateSkills(skill)\n    }\n  });\n},\n\nupdateSkills(skill) {\n  var skills = this.state.skills.filter((s) =\u003e { return s.id != skill.id });\n  skills.push(skill);\n\n  this.setState({ skills: skills });\n},\n```\n\n\u003cbr\u003e\n\nFirst we filter out the skill that matches `skill.id`, then we are pushing the updated skill onto the filtered skills array and then we are updating the state with the correct values.\n\n\u003cbr\u003e\n\n### 10. Updating the level of a skill\n---\n\nLast thing we will do before we see if there are any opportunities to refactor our code is updating the level of a skill. Either we could have three buttons corresponding to each of the levels (bad, half-bad and fantastic), or, we could have an up arrow and a down arrow and when the user clicks either it levels up and down respectively.\n\nIt seems like implementing the arrows will take slightly more work, so let's do that.\n\nFirst, we need our arrow buttons - and we'll be adding our first css!\n\n\u003cbr\u003e\n```\n$ touch app/assets/stylesheets/skills.scss\n```\n\n\u003cbr\u003e\n\n**app/assets/stylesheets/application.scss**\n```\n@import \"skills\";\n```\n\n\u003cbr\u003e\n\n**app/assets/stylesheets/skills.scss**\n```\n.skill-level {\n  display: inline-flex;\n}\n\n.skill-level button {\n  background-color: pink;\n  border: 1px solid deeppink;\n}\n```\n\n\u003cbr\u003e\n\nWrap the `level` with the arrow buttons.\n\n\u003cbr\u003e\n\n**app/assets/components/javascripts/_skill.js.jsx**\n```\n\u003cdiv className='skill-level'\u003e\n  \u003cbutton type=\"button\" className=\"btn btn-default btn-sm\"\u003e\n    \u003cspan className=\"glyphicon glyphicon-triangle-bottom\"\u003e\u003c/span\u003e\n  \u003c/button\u003e\n\n    \u003cp\u003e\u003cstrong\u003eLevel:\u003c/strong\u003e {this.props.skill.level}\u003c/p\u003e\n\n  \u003cbutton type=\"button\" className=\"btn btn-default btn-sm\"\u003e\n    \u003cspan className=\"glyphicon glyphicon-triangle-top\"\u003e\u003c/span\u003e\n  \u003c/button\u003e\n\u003c/div\u003e\n```\n\n\u003cbr\u003e\n\nLet's write down a todo-list for this feature.\n\n1. Add click events to the arrows - bind an argument to the function so we know which button was clicked\n2. In the click handler, check if it's possible to decrease/increase the level (is it already the lowest/highest value?)\n3. Depending on #2, send a request to the server to update the status\n\nFor #3 we can use the same chain we used for editing the name and the details (`this.props.handleUpdate()`).\n\nLet's add a click listener for both arrow buttons and bind arguments to them.\n\n\u003cbr\u003e\n\n**app/assets/components/javascripts/_skill.js.jsx**\n```\n\u003cdiv className='skill-level'\u003e\n  \u003cbutton type=\"button\"\n          className=\"btn btn-default btn-sm\"\n          onClick={this.handleLevelChange.bind(this, 'down')}\u003e\n    \u003cspan className=\"glyphicon glyphicon-triangle-bottom\"\u003e\u003c/span\u003e\n  \u003c/button\u003e\n\n    \u003cp\u003e\u003cstrong\u003eLevel:\u003c/strong\u003e {this.props.skill.level}\u003c/p\u003e\n\n  \u003cbutton type=\"button\"\n          className=\"btn btn-default btn-sm\"\n          onClick={this.handleLevelChange.bind(this, 'up')}\u003e\n    \u003cspan className=\"glyphicon glyphicon-triangle-top\"\u003e\u003c/span\u003e\n  \u003c/button\u003e\n\u003c/div\u003e\n\n```\n\n\u003cbr\u003e\n\nNow we need logic in `handleLevelChange()` to decide whether or not to update the level when we click either button.\n\n\u003cbr\u003e\n\n**app/assets/components/javascripts/_skill.js.jsx**\n```\nhandleLevelChange(action) {\n  var levels  = ['bad', 'halfbad', 'fantastic'];\n  var name    = this.props.skill.name;\n  var details = this.props.skill.details;\n  var level   = this.props.skill.level;\n  var index   = levels.indexOf(level);\n\n  if (action === 'up' \u0026\u0026 index \u003c 2) {\n    var newLevel = levels[index + 1];\n    this.props.handleUpdate({id: this.props.skill.id, name: name, details: details, level: newLevel})\n  } else if (action === 'down' \u0026\u0026 index \u003e 0) {\n    var newLevel = levels[index - 1];\n    this.props.handleUpdate({id: this.props.skill.id, name: name, details: details, level: newLevel})\n  }\n},\n\n```\n\n\u003cbr\u003e\n\nThat code is working. It's not pretty, but it's working.\n\nI'm going to keep it like this and deal with it first thing in next section - time to refactor!\n\n\u003cbr\u003e\n\n### 11. Refactor\n---\n\nTo refactor the code above, it's a good start to try to state what is happening in the function.\n\n'If the level can be changed, send the updated object up the chain to be updated'.\n\nThat gave me this:\n\n\u003cbr\u003e\n\n**app/assets/components/javascripts/_skill.js.jsx**\n```\nhandleLevelChange(action) {\n  if (this.levelCanBeChanged(action)) {\n    var skill = this.updatedSkill()\n    this.props.handleUpdate(skill);\n  }\n},\n\n```\n\n\u003cbr\u003e\n\n`this.levelCanBeChanged(action)` will return either true or false. We send it the action, either 'up' or 'down', and checks the given limit meets a condition.\n\n**app/assets/components/javascripts/_skill.js.jsx**\n```\nhandleLevelChange(action) {\n  var levels  = ['bad', 'halfbad', 'fantastic'];\n  var level   = levels.indexOf(this.props.skill.level);\n\n  if (this.levelCanBeChanged(action, level)) {\n    var skill = this.updatedSkill()\n    this.props.handleUpdate(skill);\n  }\n},\n\nlevelCanBeChanged(action, limit) {\n  return action === 'up' \u0026\u0026 limit \u003c 2 ||  action === 'down' \u0026\u0026 limit \u003e 0;\n},\n```\n\n\u003cbr\u003e\n\nNext up is `updatedSkill()`. We return an object with an updated level that is set by checking the action and moving either up or down in an array.\n\n\u003cbr\u003e\n\n**app/assets/components/javascripts/_skill.js.jsx**\n```\nupdatedSkill(action, index) {\n  var id       = this.props.skill.id;\n  var name     = this.props.skill.name;\n  var details  = this.props.skill.details;\n\n  var levels   = ['bad', 'halfbad', 'fantastic'];\n  var change   = action === 'up' ? 1 : - 1;\n  var newLevel = action ? levels[index + change] : this.props.skill.level;\n\n  return {id: id, name: name, details: details, level: newLevel}\n},\n```\n\n\u003cbr\u003e\n\nWe can also refactor out the part where we set the new level to a function.\n\n\u003cbr\u003e\n\n**app/assets/components/javascripts/_skill.js.jsx**\n```\ngetNewLevel(action, index) {\n  var levels   = ['bad', 'halfbad', 'fantastic'];\n  var change   = action === 'up' ? 1 : - 1;\n\n  return action ? levels[index + change] : this.props.skill.level;\n},\n```\n\n\u003cbr\u003e\n\nThis looks better, but there is more to do in this component. `onUpdate()` can be made better. Let's make it a bit more readable.\n\n\u003cbr\u003e\n\n**app/assets/components/javascripts/_skill.js.jsx**\n```\nonUpdate() {\n  if (this.state.editable) {\n    var skill   = { id: this.props.skill.id,\n                    name: this.state.name,\n                    details: this.state.details,\n                    level: this.props.skill.level }\n\n    this.props.handleUpdate(skill);\n  }\n\n  this.setState({ editable: !this.state.editable })\n},\n```\n\n\u003cbr\u003e\n\nThe handler function for the level change, `onLevelChange`, can be renamed to `onUpdateLevel` to better match the naming pattern we have for the editing handler function. To make the following code working below I had to update the implemenation of `this.props.handleUpdate`, `handleUpdate()` in the `Body` component. In this function we are now only passing up the attributes we need to update (we need the id for the Ajax call). We can therefore also drop the `level` attribute in the skill object in `onUpdate()`.\n\n\u003cbr\u003e\n\n**app/assets/components/javascripts/_skill.js.jsx**\n```\nonUpdateLevel(action) {\n  if (this.canChangeLevel(action)) {\n    var level = this.getNewLevel(action)\n    var skill = {id: this.props.skill.id, level: level }\n\n    this.props.handleUpdate(skill);\n  }\n},\n```\n\n\u003cbr\u003e\n\nSince we are no longer passing up a full skill object we can no longer use it to update the skill in `updateSkills()`. Instead, we need our API to pass the updated object back so we can keep replacing the old skill with the new skill in `updateSkills`. Otherwise we would have to update only the attributes that were present in the skill object which feels... a bit strange. Also, it's way safer to use the updated object from our API and if we can, we wouldn't we?\n\n\u003cbr\u003e\n\n**app/assets/javascripts/components/_body.js.jsx**\n```\nhandleUpdate(skill) {\n  $.ajax({\n    url: `/api/v1/skills/${skill.id}`,\n    type: 'PUT',\n    data: { skill: skill },\n    success: (skill) =\u003e {\n      this.updateSkills(skill)\n    }\n  });\n},\n\n```\n\n\u003cbr\u003e\n\n\n**app/skills/controllers/api/v1/skills_controller.rb**\n```\ndef update\n  skill = Skill.find(params[\"id\"])\n  skill.update_attributes(skill_params)\n  respond_with skill, json: skill\nend\n```\n\n\u003cbr\u003e\n\n### 12. Filter Skills by Level\n---\n\nOur next step is to filter skills based on the level. Our goal is to create a select input that has an option for each level. When the select input is changed it will show only the skills at the selected level to the user. For example, if the user wants to review the 'halfbad' skills they would select 'halfbad' from our soon to be created dropdown and without having to refresh the page, we would want only the skills with a level of 'halfbad' to show up in our `AllSkills` component.\n\nFirst let's create a SelectFilter component.\n```\ntouch app/javascripts/components/_select_filter.js.jsx\n```\nIn our `_select_filter` we will create a component that has a selector and label. Our `SelectFilter` class renders a Label, and a Select input with four options (all, bad, halfbad, and fantastic).\n\n**app/assets/components/javascripts/_select_filter.js.jsx**\n```\nvar SelectFilter = React.createClass({\n  render (){\n    return(\n      \u003cdiv\u003e\n        \u003clabel\u003e\n          Filter By\n        \u003c/label\u003e\n        \u003cselect className=\"form-control\"\u003e\n          \u003coption value=\"all\"\u003eAll\u003c/option\u003e\n          \u003coption value=\"bad\"\u003eBad\u003c/option\u003e\n          \u003coption value=\"halfbad\"\u003eHalfbad\u003c/option\u003e\n          \u003coption value=\"fantastic\"\u003eFantastic\u003c/option\u003e\n        \u003c/select\u003e\n      \u003c/div\u003e\n    )\n  }\n}\n```\n\u003cbr\u003e\n\nTo make sure the `SelectFilter` component looks the way we want, we will add it to the `Body` component in our `_body.js.jsx` file, fire up the server (if you haven't yet done so) with `rails s`, and then navigate to `localhost:3000`.\n\n**app/assets/components/javascripts/_body.js.jsx**\n```\nrender() {\n  return (\n    \u003cdiv className=\"container\"\u003e\n      \u003cNewSkill handleSubmit={this.handleSubmit} /\u003e\n      \u003cSelectFilter/\u003e\n      \u003cAllSkills skills={this.state.skills}\n                 handleDelete={this.handleDelete}\n                 handleUpdate={this.handleUpdate} /\u003e\n      \u003c/div\u003e\n  )\n}\n```\nIf everything is wired up correctly, you should now see a select input with the four options in between the `NewSkill` form and the `AllSkills` list.\n\n\nNow we will actually create our filtering functionality. The big picture is that we want to filter based on the level, so we will start our journey by passing a `handleFilter` property to our `SelectFilter` component. This property we will call whenever we want to actually filter our skills, so we need to assign it a callback - `this.filterSkillsByLevel`.\n\n**app/assets/components/javascripts/_body.js.jsx**\n```\nrender() {\n  return (\n    \u003cdiv className=\"container\"\u003e\n      \u003cNewSkill handleSubmit={this.handleSubmit} /\u003e\n      \u003cSelectFilter handleFilter={this.filterSkillsByLevel} /\u003e\n      \u003cAllSkills skills={this.state.skills}\n                 handleDelete={this.handleDelete}\n                 handleUpdate={this.handleUpdate} /\u003e\n      \u003c/div\u003e\n  )\n}\n```\n\u003cbr\u003e\nI am sure you noticed that inside of our `handleFilter` property we have a function called `filterSkillsByLevel`, so let's go ahead and create that within our `_body.js.jsx`.\n\n**app/assets/components/javascripts/_body.js.jsx**\n```\nfilterSkillsByLevel(level) {\n  console.log(\"about to filter\");\n},\n```\nWe will add the functionality of filtering in the above `filterSkillsByLevel(level)` function. But first, let's wire it all together and make sure that when the user changes the select dropdown, this `filterSkillsByLevel` function is invoked.\n\n\nLet's add an `onChange` event to our select input that will call the `updateFilter` function. In order to accomplish that we must bind the object 'this' to our function call. In this case, the 'this' object refers to the `SelectFilter` component. This is important because if we did not bind 'this', when we get into the updateFilter function call we would not be able to call `this.state` or `this.props` since in that case, this would refer to the function `updateFilter`, not the component `SelectFilter`. That is a lot of this's and thats and for what its worth, this is probably the toughest part of React!\n\n**app/assets/components/javascripts/_select_filter.js.jsx**\n```\nrender (){\n  return(\n    \u003cdiv\u003e\n      \u003clabel\u003e\n        Filter By\n      \u003c/label\u003e\n      \u003cselect className=\"form-control\" onChange={this.updateFilter.bind(this)}\u003e  \n\n    ...\n```\nNow we need to create an updateFilter function within the FilterSelect component which will be invoked whenever there is a change on our element.\n\n**app/assets/components/javascripts/_select_filter.js.jsx**\n```\nupdateFilter(event) {\n  this.props.handleFilter(event.target.value)\n}\n```\nRemember, since we bound the object 'this' to the function call in our `updateFilter`, 'this' refers to the entire component. This gives us access to all of the properties of the `SelectFilter` component. We need the `handleFilter` property, which we pass into the component when we render it in the Body. The `handleFilter` property points to the `filterSkillsByLevel` function in the `Body` component.\n```\n         Main\n       /      \\\n  Header        Body\n            /      \\                 \\\n        NewSkill   SelectFilter    AllSkills\n                                       \\\n                                      Skills * n\n```\nFor additional context, in the above diagram when the user selects a value to filter by in the `SelectFilter` component, the `handleFilter` property is invoked which sends a message up to the `body` component. This message then changes the state of our `body` component which in turn re-renders the list of visible skills.\n\nLet's pass in the value of the select input from the `SelectFilter` to the `Body`, which we get from the event object.\n```\nevent.target.value\n```\nIf everything is working properly, when you reload the page and select an option from the selector, you should see \"about to filter\" logged to the console.\n\n\nNext we need to actually make the `filterSkillsByLevel` function filter our skills list based on the value passed in from the select input. Let's start by creating a variable called `newSkills` which will represent the skills we want to display for our user based on the selected level in our `SelectFilter` component.\n\n**app/assets/components/javascripts/_body.js.jsx**\n```\nfilterSkillsByLevel(level) {\n  let newSkills = null;\n}\n```\nIf the selected level does not equal all, then we want to filter the skills stored in `this.state.skills` based on the selected level.\n\n**app/assets/components/javascripts/_body.js.jsx**\n```\nfilterSkillsByLevel(level) {\n  let newSkills = null;\n  if (level !== 'all') {\n    let newSkills = this.state.skills.filter(skill =\u003e skill.level === level);\n  }\n}\n```\nNow if the level passed in to our `filterSkillsByLevel` function is 'all' newSkills will be null, which is falsey. Otherwise it will be an array of skills with level equal to the passed in level. All we need to do is set the state of our app like this:\n\n**app/assets/components/javascripts/_body.js.jsx**\n```\nfilterSkillsByLevel(level) {\n  let newSkills = null;\n  if (level !== 'all') {\n    let newSkills = this.state.skills.filter(skill =\u003e skill.level === level);\n  }\n  this.setState({filteredSkills: newSkills});  \n},\n```\n\nWe are also going to add the `filteredSkills` property to our initizalize function. We do this to show explicitely what the initial state of our component should be.\n\n**app/assets/components/javascripts/_body.js.jsx**\n```\ngetInitialState() {\n  return { skills: [], filteredSkills: null }\n},\n```\n\nThe last thing we need to do is selectively render all the skills in `this.state.skills` if there is no filter being applied (e.g. 'all' is selected) or render the skills in `this.state.filteredSkills`. To do this we are going to use the `||` operator which will return the value on the left side if it is truthy and otherwise return the value on the right. Looking at our render function in our `Body` component we'll make the following change in how we render the `AllSkills` component:\n```\n\u003cAllSkills skills={this.state.filteredSkills || this.state.skills}\n           handleDelete={this.handleDelete}\n           handleUpdate={this.handleUpdate} /\u003e\n```\nIn the above code, when the `AllSkills` component is rendered, it will first set the property `skills`. To do so it will look at `this.state.filteredSkills`. If `this.state.filteredSkills` is truthy it will take `this.state.filteredSkills` for the `skills` property. Otherwise it will store `this.state.skills` as the skills property.\n\n`this.state.filteredSkills` will be null when the component is first rendered, so it will evaluate to be false. It will also be null when the user selects 'all' from the `selectFilter` component. In both of these cases, the `AllSkills` component will render with `this.state.skills` or all the skills as its `skills` property.\n\nHowever, if a filter value is selected, `this.state.filterSkills` will be an array of filtered skills and therefore evaluate to be true. In that case, the `AllSkills` component will render with the filtered skills stored in `this.state.filterSkills` as its `skills` property.\n\nAll together our updated render function will look like this:\n\n**app/assets/components/javascripts/_body.js.jsx**\n```\nrender() {\n    return (\n      \u003cdiv className=\"container\"\u003e\n        \u003cNewSkill handleSubmit={this.handleSubmit} /\u003e\n        \u003cSelectFilter handleFilter={this.filterSkillsByLevel} /\u003e\n        \u003cAllSkills skills={this.state.filteredSkills || this.state.skills}\n                   handleDelete={this.handleDelete}\n                   handleUpdate={this.handleUpdate} /\u003e\n      \u003c/div\u003e\n    )\n  }\n```\nNow we have a very snappy feeling filter function. We did it!\n\n### 13. You are awesome\n---\n![](http://reactiongifs.us/wp-content/uploads/2013/02/youre_awesome_carl_sagan.gif)\n\n\nPossible extensions:\n\n- extract out API calls to service\n- add styling (use `className` instead of `class` when adding CSS classes)\n- filter skills by level (3 click events on 3 buttons which hides non matching skills)\n- filter skills by text (use `onChange` event handler)\n- tag skills (personal, professional, urgent)\n- create groups of skills\n\n\nIf you are interested in adding sections to this tutorial or find areas for improvement/correction/clarification, please submit a pull request.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbiglovisa%2Fcreact","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbiglovisa%2Fcreact","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbiglovisa%2Fcreact/lists"}