Skip to main content

React Simplicity

This is just a quick intro to React to show how easy it is on a very basic level. React is often compared to Angular, but the two are very different: Angular is more of a framework, whereas React is more of a library. So, with React, we can make Components, and in so doing, we can intersperse plain Javascript to instill behavior. This article is not showing (or using) best practices, or a recommended structure. It's purpose is only to show how easy the basic mechanics of React are.

Let's grab the getting started cli from React's page
npm install -g create-react-app
create-react-app my-app

cd my-app
npm start

After this is done, and you have the project displayed in your browser, let's experiment. A boiler-plate header we can use for each new class can be as simple as:

/src/Foo.js

import React, { Component } from 'react'; 

class Foo extends Component { 
  render(){ 
    return(); 
  } 
} 
export default Foo;
So, all that we need to change to get started is the name of the class you want to create (replace Foo with that name). And following the convention, the name of the file containing our class is the name of the class, and they're both capitalized. Also note the function, render(). All classes based on React require this method. From this method, a single DOM element is returned. Let's create one more class:

/src/Bar.js

import React, { Component } from 'react';
import Foo  from './Foo';

class Bar extends Component {
  render() {
    return ();
  }
}
export default Bar;

The thing to note here is, I am having Bar include Foo. The reason for this is because Bar is going to render a Foo Component. The structure will be: the main component of our application, "App.js" will contain our component, "Bar.js". And, "Bar.js" will contain our component, "Foo.js". Let's flesh out Foo:

/src/Foo.js

import React, { Component } from 'react';

class Foo extends Component {

  constructor() {
    super();
    this.user = {
        firstName: 'Moe',
        lastName: 'Bettah'
    };
  }

  displayName() {
    return this.user.firstName + ' ' + this.user.lastName;
  }

  render(){
    return(
      <h1>Hello, {this.displayName()}!</h1>
    );
  }
}
export default Foo;

So this simplistic class renders, "Hello, Moe Bettah!". You can see that the larger portion of the class is plain old Javascript. The React portion of the class is just the render() function. Every render() must return a single element. It can be a complex element, like a div containing numerous other elements, but in that case, we are still just returning a single div (and its contents). Now, let's flesh out Bar:

/src/Bar.js

import React, { Component } from 'react';
import Foo  from './Foo';

class Bar extends Component {
  render() {
    return (
      
<h3>Here's a greeting...</h3>
); } } export default Bar;

Here, notice that our Bar class file includes Foo. Bar is just a plain container component. It renders a div, which contain's our Foo component. The Foo component through the magic of React, can now be referred to as, , and so that is how we refer to it in Bar. Notice that we also add some content to Bar's returned div, just above our Foo element. So we have Bar, which renders a bit of text and also renders Foo. All that remains is to add this to our App.

We need to add an import to the top App.js:

import Bar  from './Bar';

And finally, we need to add our component. Note that App follows the rule of only rendering a single element. In this case, a div with the css class of "App". There can be any amount of content within this singly returned div, and here there is indeed content added. Now, just place our tag just above the closing div in App's returned div. As an aside, note that the class attribute's are referred to as className in camel-case. There are some simple rules in attribute naming that React follows, which you can read in the docs. Finally, let's add a couple gratuitous tests to the single test that is autogenerated for us. Open, "App.test.js" and have a look at the file. We're going to add to this, to make testing easier.

On the command line, within the top directory, my-app enter:

npm i --save-dev enzyme

Enzyme allows us to easily test React components. See the included test in App.test.js?

Have a look at how easy it is with enzyme:

it('renders without crashing', () => {
  const app = shallow()
});

That's it! So, let's make two gratuitous test's, just to get an idea of how to access and test components we build.

At the top of "App.test.js" add the following:

import { shallow } from 'enzyme';
import App from './App';
import Foo from './Foo';
import Bar from './Bar';

We're including enzyme and all three of our classes. The App test is already written, let's make a couple test's against Foo and Bar:

it('shows bar\'s text, "Here\'s a greeting..."', () => {
    const bar = shallow();
    const test_content = <h3>Here's a greeting...</h3>
    expect(bar.contains(test_content)).toEqual(true); 
}); 

it('the name Nick is included in the display', () => { const foo = shallow(); 
  const test_content = <h1>Hello, Moe Bettah!</h1>
  expect(foo.contains(test_content)).toEqual(true); 
});

Here, in each case we're grabbing the component we want to test using enzyme's shallow() method. Within our component's, we want to test for included HTML elements. In the case of Bar, we're checking the static text within it's <h3> element. In Foo, we're checking that the dynamic text we are inserting is actually present. All very easy stuff. That's it. Super basic, super easy. There is a great deal more to know of course, but this is a friendly starter to show that it's not complex to begin tackling React.

Comments

Popular posts from this blog

Java application opening then immediately closing on OSX

I have had several occasion's where Java apps would open, and then immediately close.  Often, I don't have the time to dig into the reason, as they aren't crucial.  So, I just move on. Recently, I was maddened by this happening to an application ( see other blog post on Kindle Previewer ) I really needed to use, so I had to get into the trench.  After cracking open the app, and rooting through the various files, I did some spot-checks of the java version used to build the jars ( 2 bytes at offsets 6 & 7 ), as well as had a look at the info.plist, which had the JVMVersion key set at 1.5+. Since Oracle took over Java, Apple has essentially abandoned it to them, and hasn't done an update I *think* since version 6. All of Apple's Tooling for Java stops with JVMVersion key's of 6* and 6+.  The short answer to all this is, if something was built using Apple's AppBundler tools, and you have updated Java on your Mac to 7 or above, you're probably SOL to g...

The Easy Way to Set up Emacs for Clojure Development on OS X

I had mixed results following The clojure-doc tutorial for Emacs, and found I had to do a few modifications. Following the recipe is easy: I was not able to easily get Aquamacs to work. Frankly, I lost interest after the initial try, and just went with the emacs build for OSX. I might mess with Aquamacs at some future point, but for now, let's just stick with Emacs proper. Install Emacs from brew First, set up Emacs from brew: $ brew install emacs --cocoa --srgb $ brew linkapps Emacs NOTE If you already have Emacs in your Applications folder, the second brew command will fail. To make sure we're on the same page, just rename Emacs.app to something else, like EmacsCocoa.app or whatever, then re-run the second brew command to link the Emacs distribution you just installed with brew to your Applications folder. After it successfully runs, you'll have a link in your Applications folder called, "Emacs". Clicking it will open the GUI version of Emacs....

Boost on OS X using the brew boost keg

I was installing boost today using the *brew keg*, which shows it's for the latest version, 1.55.0, but I kept running into errors. --HEAD --with-mpi In the case of #1, it kept puking every time it tried to grab boost from svn. In the case of #2, no matter what I did, including this option kept giving a warning about Python support soon to be deprecated. And yes, I tried the --without-python` option. It just wasn't happening. I don't know if it's a problem with the keg, or a problem with this particular build of Boost. Finally, I was successfully able to get things to build using: brew install boost --c++11 --with-icu --without-python --without-single