Skip to content

Instantly share code, notes, and snippets.

@timfitzzz
Last active November 27, 2021 17:10
Show Gist options
  • Save timfitzzz/0037a18e90dc7a86c646 to your computer and use it in GitHub Desktop.
Save timfitzzz/0037a18e90dc7a86c646 to your computer and use it in GitHub Desktop.

Reading about React.js

— Here's a walkthrough of the Getting Started, basically:

This was dope because I went from "what the hell is React" to "here is a list of things that I now know about React.js:

  1. "React is the 'view' in the application."
  2. React "gets you to think in components." The writer of this walkthrough compares it to Legos, which is intriguing. Components is an interesting term; how does it relate to layers of abstraction already in use in JS, like modules? Ahh, a new term: component-driven development.
  3. React has "this virtual DOM thing", which "makes the rendering super fast but still keeps it easily understandable and controllable at the same time". This strikes me as a ridiculous sentence on a number of levels. But interesting concept I suppose!
  4. React is "mainly a concept". It is more a concept than it is a library! OK cool I like concepts. What's the concept?
  5. React is "an ecosystem" in which "you have to pick your own tools and build your own ~framework." Ooh, a squiggly line! So it's a thing to make things that are sort of like frameworks? Is it sort of like a framework for frameworks?
  6. For something called "pub-sub", it uses Node's "EventEmitter", so those are two things I don't fully understand. Is the EventEmitter the thing that just like keeps track of stuff that happens? I am going to take a stab at "pub-sub" and guess that it means publication-submission or basically what happens via HTTP. Or maybe it also refers to DB activity, like it's the same as I/O? Or maybe this is when you go to a traditional irish pub in Boston and order a hero sandwich and they say, "whatdyamean you want a hero, you some kind of New Yawk Yankee? It's a sub, fella." "Also, we are an irish pub and we don't sell subs, try Little Steve's.""

OK so now this walkthrough is promising to deliver the concept of the Virtual DOM in a nutshell. Let's continue our walkthrough of the walkthrough of the getting started walkthrough….

  1. We know what the DOM is, right? That's the document object model, which basically is what the web browser uses HTML and CSS, and potentially Javascript, to build before displaying a web view to you. You, the lovely user.
  2. The author posits that in general, to change the DOM requires awareness of two things: a) when there are new changes to apply (new data), and b) what DOM elements to change.
    1. To detect changes, "React uses an observer model instead of dirty (continuous) checking". It doesn't have to calculate changes, then, because it somehow already knows. Because it is observing, I gather? This, the author writes, "reduces the calculations" and therefore makes the app smoother. OK.
    2. But "the really cool idea here" is "how it manages the DOM manipulations," which I'm guessing is supposed to be b. To deal with this, React "builds the tree representation of the DOM in the memory and calculates which DOM element should change." DOM manipulation is apparently heavy so it should be minimized, and React actively tries to leave as much of it alone as possible, which it can do a better job of (and faster) because it has a complete picture, I would infer.
    3. Thus, React apparently has a "diffing algorithm" which uses a tree representation of the DOM and re-calculates subtrees when parents are modified. So you should "be aware of your model changes", because they require re-rendering subtrees apparently. So it punishes you for needless changes? But I am told not to be sad, for "later we will optimize this behavior together." Some foreshadowing references to **shouldComponentUpdate(), **which sounds like a React function, and ImmutableJS which seems like a library.

Next, something about rendering on the server. The author suggests that somehow this client-side (I think?) Virtual DOM eases server-side rendering as well. Oh word? Howzat?

WELL< it is simply that React is "smart enough to recognize that the markup is already there (from the server) and will add only the event handlers on the client side." So it sounds like it can just take HTML and do some kind of parsing to integrate it into its own steez?

OOH, an "Interesting:" ! Is it? Hmmm… "React's rendered HTML markup contains data-reactid attributes, which helps React tracking DOM nodes." OK I guess that's kind of interesting, sure guy why not. So but I guess despite the much-balleyhooed Virtual DOM, React still needs to place markers in the actual DOM. Which is fine, I don't see why that's not fine, w/e.

OK, so there wasn't much about that. Quick pivot to a new H1: "Component-driven development", which the author admits was initially difficult for him to pick up early on in his learning of React.

"In the component-driven development, you won't see the whole site in one template." OK, that sounds just like templating engines like Jade, right? But there must be more to it somehow. Quick shoutout to tests (YO WHAT UP TESTS), which React facilitates, as well as his friends "easier to understand" and "easier to maintain" which React also makes things.

The next section is entitled "How should I imagine it?", it being "component-driven development". The example provided is of a 'component hierarchy', which correlates directly with a demonstration view:

  • FilterableProductTable (the entire view)
    • Search Bar (search box)
    • ProductTable (containing results)
      • ProductCategoryRow (separator row)
      • ProductRow (product row)

OK, so this is pretty damn familiar. I just mocked up a potential StoryPad view in Pinegrow Web Designer with basically an identical DOM:

  • .story-main
    • .item-container
      • .item-leftside
      • .item-rightside

But my names aren't as precise. What if the names more closely adhered to this model?

  • .StoryElementsContainer
    • .ElementRow
      • .ElementContent
      • .ElementMeta

OK that's interesting…

So, next: "What should a component contain?"

1st: follow the "single responsibility principle": each component should be responsible for only one thing. Break components down into smaller ones until that's how they work. This is obviously consistent with the domain modeling stuff I've been learning in TLC, particularly from Guillaume's example and tutelage. It's a habit I am still wrapping my mind around, to be completely honest. (For one thing, what's a "thing"? My DOM structure above treats "ElementMeta" as one thing. But really, that Meta could include a number of things: annotations, action buttons, etc. Should those all be separate components?)

OK, so he's offering code for a simple component in ES5, but the rest of the tutorial seems to prefer ES6.

ES5:

var HelloComponent = React.createClass({

render: function() {

return Hello {this.props.name} ;

}

});

ES6:

class HelloComponent extends React.Component {

render() {

return Hello {this.props.name} ;

}

}

I really haven't delved into ES6 at all yet. But what I can infer from these examples is:

— there are actual classes in ES6, so that's undoubtedly a whole thing to learn.

— somehow HTML goes right in there? Wait no that's something else —

JSX!

So no, the actual ES6 w/o JSX looks like:

render () {

return React.createElement("div", null, "Hello ",

this.props.name);

}

But React likes JSX, which lets you just drop HTML into your JS like it's no thing. This is somewhat strange. But yeah you don't actually have to create the element with React.createElement, as long as you can just return the HTML as in ES6? Weird.

The X in JSX, it turns out, actually stands for XML, not HTML. So there's some kind of compilation that happens of the JSX to turn it into JS…

Anyway: other stuff about components:

Components can have:

  • an internal state
  • logic
  • event handlers
  • inline style

So, all of the pieces of a good view.

With JSX, at least, you can use {this.props.user.etc} to drop variables in as HTML properties or code, similar to Handlebars / Jade.

OK next a quick shout out to ES6 which is apparently "here" and well-suited to React. Author recommends Babel as a transpiler between ES6 and ES5, to make sure to maintain support for all browsers.

OK, next: Bundlers… author recommends something called Webpack. What's this??

Apparently it "bundles our code and the required packages into the output files for the browser." There's also Babel which they want to use to do transpiring as previously mentioned. Then you basically define a js object with the configuration of the packing… etc etc whatever

Author recommends a structure that separates the "React app from the client and server code." Theirs would be an "isomorphic app", which means that it can run on both client side and server side. Hmm.

Author recommends Jest to test React apps, since the framework and React share a developer — Facebook.Testing should be straightforward since you're adhering to "single responsibility". (Potentially hot link: Jest React tutorial.)

So, that's it. I'm supposed to now:

  • understand why React is fast and scalable (presumably, it's scalable because it is fast, and it's fast because of the more efficient Virtual DOM)
  • understand how different its approach is (I sort of do, although component-driven seems pretty non-different from what I've been learning already, though I can see how it might be different from other things I haven't really learned much about yet)
  • understand how React handles rendering (kind of)
  • understand what component-driven development is — I think I do; it's:
    • one-function per chunk
    • component hierarchy
  • understand how to set up / organize my project, which I do but only by rote, since I still don't understand how or why you'd run the same code on both the front and the back end.

OK that's cool for now.

————

Plotting out the twinput front end with modular component structure ala React.js:

  • HeaderRow
    • EventTitleColumn
    • EventDetailsColumn
    • EventControlPanel
  • StoryContainer
    • StoryBrowserColumn
      • Paginater
      • StoryElementsContainer
        • StoryElement
          • ElementBody
            • ElementUser
              • ElementUserAvatar
              • ElementUserName
              • ElementUserScreenName
            • ElementContent
            • ElementFooter
          • ElementTools
    • SidebarColumn

I figure I should probably find some actual exercises to do with React, so that I can experiment with it without taking my mind off of where I'm already at with my current approach to 'twinput'.

I settle on this walkthrough, React JS Tutorial and Guide to the Gotchas ( ).

I know this is immediately going to be better. It starts with a better explanation of the Virtual DOM and also a really helpful primer on JSX.

OK I think I'm going to try to use the info laid out in the tutorial above to port a few of twinput's components to React.

First though I'm going to read and understand one more thing: . I found this via a Brackets blog post about switching Brackets, which itself is a jQuery app, to React. It essentially walks through a reconstitution of React from scratch, to explain what it does. I have a feeling this will be helpful.

——

Right off the bat: "Rerendering everything (and only applying it to the DOM when something actually changed) vastly simplifies the architecture of our app. **Observables+DOM elements is a leaky abstraction, **and as a user I shouldn't need an intimate knowledge of how the UI is kept in sync with my data. This architecture opens up lots of various ways to optimize the rendering, but it's all completely transparent to the user."

Where is the leaky abstraction? I don't know what "Observables+DOM" means. This is because I don't know what observables really means, I guess, even though it feels like it should be obvious. Anyway, I'd like to understand this.

I do understand the gist, though: rendering the DOM programmatically -- building a brand-new abstraction to interface with it — is much better than the weirdness of scripting manipulations to what the user sees. In fact, the concept of the virtual DOM really makes jQuery seem rather primitive. It reminds me of how simple its initial applications were, and probably still its most common ones are.

OK, so here's some more explanation of his beef:

"Aren't you tired of having to query the DOM tree and manually manage the structure to create UIs? Web Components doesn't solve this at all, it just tries to encapsulate the work. The problem is that building apps is building components, so you inevitably are forced back into the manual DOM management to create your app-specific components (like how you constantly have to create directives in Angular). You also need to jump into JavaScript to configure and wire up any Web Components you used. It's a very messy abstraction, and fools you into desiring a pure HTML-based declarative way to write apps, which is like wanting steak but eating liver."

He says frameworks help. But templates and controllers are still separated and data binding therefore leaks into the app.

Anyway:

Flow is, data is passed down, events flow up.

That's helpful. "State flows down," he says elsewhere. Data that is to be displayed becomes state for the UI components. Events are input that is intended to modify the data, it flows up to the app and then the changed state flows back down.

A component has **this.props, its properties. **"Properties should never be changed" — a function should never change its properties. But state can be mutated — by events, which then trigger re-rendering. Changing props wouldn't be helpful because re-rendering would cause components to re-inherit them based on the render code anyway.

Another usefully clarifying / best practices thought: "The difference between state and properties can be useful. It makes it clear what state the component owns. It's best to keep most of your components stateless, and isolate state into as few places as possible. This makes it easy to rationalize about your app and how it changes over time. We will explore this more in the next section."

Next: Explicit App State.

"You're probably already familiar with the pattern of attaching event handlers to components." Not so much, I should probably look into this. But I think I have an idea of what he's talking about…

Javascript functions can be bound into the controller declaratively within render().

He encourages the reader to "make data flow clear and simple" because "it encourages you to keep state in as few places as possible and make most of your components stateless". I believe by stateless he means there's nothing to keep track of inside of the component. " But components can use state, provided they have a getInitialState method that returns the initial-state object.

The benefits of "tearing apart state from the component instance" include:

  1. "It's adaptable." Says state object doesn't have to be native Javascript; it can be anything you return in getInitialState. So you could swap stuff in, like something called "persistent data structures"
  2. "It's easy to snapshot." Once you have generated a component based on a given state, you know exactly what it's going to look like. **If you save the state object somewhere, you can load it up later and render your component exactly like it was when you saved it. **Woah, okay. I can see how dope that would be. Specifically suggests an undo system, which is v interesting.
  3. "It's easy to test and pre-render." "Can easily test components by rendering them with a specific state to an HTML string and comparing the output." Also, you can pre-render, somehow, because the client side library will "bind all the event handlers to the pre-rendered DOM" somehow.

"The principle to learn is": "Things like DOM elements are basically native objects, like an open file instance. You don't stick user-land state onto file instances, do you? They are unserializable and slow. Since the DOM doesn't contain our app state, we just have to deal with a simple JavaScript object, declaratively render a structure based on it, and let the library figure out how to reify it into DOM elements."

Ahh. So yeah that's nice: not having to get ingredients for Javascript functions out of the DOM at all. The data all lives elsewhere. That's pretty awesome.

Woah: the example app he uses, the entire state is a single object attached to the App component! OK that's pretty ill.

Oh, shit: next topic is an undo system; next app is a Twitter clone. Cool cool cool.

Right: so basically, because there is a refresh EVERY time state changes, each refresh marks a unique state, which can be saved before it is changed.

He suggests possibility of using a "versioned data store" in order to make undoing on the back end just as trivial. But to be clear, React here is serving as a quick undo for the front end, and not (yet, at least) as a way of storing state on the back end (for discussion, deliberation, etc).

"The structure of a component created within the render method is declarative, because the structure is generated based off of the app state, and nothing else. As the app state changes, so does your structure." Though its form is a bit confusing because any Javascript can be run.

——

@timfitzzz
Copy link
Author

Continuing my exploration of React.

Last time on What The Hell is React?, I built a piece of Twinput's front end using React. This version is static -- it doesn't have any interactivity. Before I go any further on building out said front-end, I'm going to walk through adding the piece of interactivity that initially began this exploration of React: the delete button.

First, though, I'm gonna read this bit from the React docs about composability. An error message that the current jsfiddle gives linked me to it:

"Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of StoryElementsContainer. See http://fb.me/react-warning-keys for more information."

It redirects to here: http://facebook.github.io/react/docs/multiple-components.html#dynamic-children -- and I've rewound now to the top of this section.

OK actually no I already know all this about separation of concerns and modularity. But here’s something new: ownership. “In React, an owner is the component that sets the props of the other components.” So, if component A is created in component B’s render() method, A is “owned” by B.

OK so with iterators, you can pass the key in as a prop (“key”) and React will know what to do with it. That’s handy.

OK I think that answers the question raised by this error message. So now on to the automation part of the thing I read before, which I think was https://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html

——

OK so getting now into a closer examination of the idea of state. Here’s a helpful breakdown:

"Think of all of the pieces of data in our example application. We have:

The original list of products
The search text the user has entered
The value of the checkbox
The filtered list of products
Let's go through each one and figure out which one is state. Simply ask three questions about each piece of data:

Is it passed in from a parent via props? If so, it probably isn't state.
Does it change over time? If not, it probably isn't state.
Can you compute it based on any other state or props in your component? If so, it's not state.
The original list of products is passed in as props, so that's not state. The search text and the checkbox seem to be state since they change over time and can't be computed from anything. And finally, the filtered list of products isn't state because it can be computed by combining the original list of products with the search text and value of the checkbox.

So finally, our state is:

The search text the user has entered
The value of the checkbox”

OK, so applying this rubric to our data, we’ve got the following things that fall into category #1 — passed in via props:

Array of tweets
Story metadata

And in #2: we don’t have anything that changes over time just yet, exactly. Nothing that changes on its own.

And in category #3: most other things can be computed based on other state or props…

So the “filtered list of products” from the example is the closest thing to what we’ve got — a list of moments in a story. The problem is, we want to edit this list. Therefore I think that all of this data actually does end up being state — as long as the data is living here in the front end. Later, if the data is being passed to the server and back when the user interacts with it, I’m not so sure it’s still state. The state is held elsewhere, right?

Anyway: the other thing is, even if the state lives elsewhere, we’re going to probably have a version of it living in the front end, right? Because otherwise we’ve got to wait for permission to change anything in the UI, and that’s not necessarily the best way to handle stuff. Especially since I am planning on putting a ‘facilitator’ between people’s operations and the data, actions may end up being visibly queued in some manner. As a view stays open, we’re not necessarily going to be concerned with what’s in the database as much as we are concerned with how it’s changed and how we can interact with that process.

Ooh, another strategy:

"For each piece of state in your application:

Identify every component that renders something based on that state.
Find a common owner component (a single component above all the components that need the state in the hierarchy).
Either the common owner or another component higher up in the hierarchy should own the state.
If you can't find a component where it makes sense to own the state, create a new component simply for holding the state and add it somewhere in the hierarchy above the common owner component.”

OK, so I’ve decided that the filter example — where the filter is state, but the data filtered is not — is the best place to start in terms of what is and isn’t state. So basically, proposed changes to the event are state, whether submitted or not. Those are the live elements. And then modifications made to the page either establish or affect those items that are state. That’s my current idea anyway… other items that will have state would be voting processes…?

So I made another component: App. And I put my state definition in there, and passed my props in from global land, as a substitute for a server. (At first I tried to just call the data from the App component; you can’t. You need to pass props in. However, other React components would seem to need to live outside of the App component — and at any rate, those ones can be referred to no problem. It’s a little bit inconsistent, seems like.

——

OK, so I’ve got some basic state established in the App component:

getInitialState: {
currentStory: {},
hiddenIndexes: [],
}

Later, some of this data will come from the server — like, if indexes have already been hidden. (We’ll see if “hidden” ends up being the right word. I am envisioning deleted objects being replaced, at least temporarily, with a placeholder that lets you undo or challenge deletions).

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