React.js Notes
JSX
JSX is a language that compiles to javascript. It lets you create javascript objects using HTML-like syntax. It’s highly recommended that you use JSX when working with React.
Basically, if you see a lot of < and > in your javascript code, you’re looking at JSX.
JSX Interpolation
Use {} to interpolate in between the < and > tags in JSX.
We’ll revisit JSX after introducing Components, a core concept in React.
Components
React components render html to be tacked onto DOM elements. All components have a `render` function which return other react components that are ultimately rendered to html, and then tacked onto DOM elements.
Component Composition
Components can be built using other components. In fact, the ability to compose components out of other components is an important characteristic of React.
Component Properties
Every component has data properties that can be accessed through `this.props`, which can be set during the instantiation of the component. The component can also access children components nested in it with the `this.props.children`. This is the mechanism for injecting data into DOM elements.
Fetching From Server
Rarely will your data be an array of objects like data above. You’ll most likely be fetching from the server. We will set the api url as a property in a component. We will use this url property during the component’s initialization to fetch data from the server.
Component State
The `this.props` of a component are immutable. They are passed from the parent and owned by the parent. As such we should not use props to hold the state of a component.
To implement state in components, we use `this.state` (no surprise there) which we alter with `this.setState()`. After `this.setState()` is called, the component automatically calls `render` again.
`setState` also takes an optional callback: `this.setState(data, callback)` which will merge the data into the component state, call the `render` function, and then call the callback.
Event Handling and Controlled Components
Components handle events by simply passing an event handler function to the event name. Some event names are `onClick`, `onKeyDown`, `onChange`, etc. You can see more here.
It’s worth noting that in the example below, the value of the input element is always equal to its state. When a component has this property, it’s called a controlled component.
Lets explore event handling and controlled components by adding a new component called `CommentForm` which will create new comments.
Parent Components Passing Functions to Child Components
Let’s add a new feature: When a new comment is created, the comment list should automatically refresh. Sounds like a pretty simple feature, right? Not so fast.
The submit form lives in the `CommentForm` component. However, the `CommentList` component is not nested within the `CommentForm`. So no function within `CommentForm` has the ability to re-render the `CommentList`. At least not directly.
To get around this, we need to go up one component, to the `CommentBox`, which is the parent to both `CommentList` and `CommentForm`, and have it provide a function called `handleCommentSubmitfunction`, which will have access to the `CommentList`. We then pass `handleCommentSubmit` into `CommentForm`. This passing of functions from parent components to child components is a very powerful pattern in React.
Component Hierarchy Design: Stateful Parent Stateless Children
In general, try to keep as few components with state as possible. A common design in react is to have many stateless components that just render data and a parent component with state that passes its state to its children through `props`. The interaction logic lives in this stateful component while the stateless components simply render.
Component Hierarchy Design: Container Components
Another component design pattern is for every component to have a container component. The container component fetches data from the server, while the child component renders. You can read more about the container pattern here.
Component State == Component UI
Because `render` is called every time `setState` is called, a component’s state is always synced to the UI. This enforces a pattern where the state should store only UI dependent data (ie. the current value in a text field, whether or not a button is toggled, etc.)
JSX Revisited
Now that we understand the basics of components, let’s finish up JSX.
As we mentioned earlier, we can interpolate into JSX using {}. We can also use this to dynamically inject child components into parent components.
Spread Em’
ES6 introduced a spread operator … which expands an iterate-able object in an iterate-able context.
JSX lets you use this spread operator to “mass assign” properties to a component, like so:
Using ES6 Classes to Create Components
There’s two ways to create React component classes. You can use `React.createClass` or you can extend `React.Component` using ES6 Classes.
These two methods of instantiation are largely similar, but there are a few differences. For example, ES6 classes don’t support mixins. If you want to include a mixin in Component, use `React.createClass` like so:
Also, the value of `this` varies between components created with `React.createClass` vs. ES6 classes extended by `React.Components`.
Importing/Exporting Across Multiple Files
In our example so far, all our components presumably live in one file. But we can break them up over multiple files and use import/export components (among functions, objects, primitives, etc.) defined in one file into other files. Note that export is not implemented natively in browsers. It is implemented in libraries like Babel.
Named Exports vs Default Exports
There are two types of exports: named exports and default exports. Named exports are used to export several variables per file, while default exports export only one variable per file.
Learning the Data/Model Layer With Redux
React only handles the view layer of an app. For the data/model layer, we can use Redux (though other options are also available). Check out these Redux.js notes if you haven’t already.