1. 程式人生 > >The Anatomy Of A React Redux App

The Anatomy Of A React Redux App

The Anatomy Of A React Redux App

If you inspect the source of a React Redux app, it could be overwhelming. But there is a method to the madness and it becomes very simple once you understand what’s going on.

To understand it better, we need to install React Developer ToolsChrome extension to Chrome browser and inspect it from within that tool.

Note: This is different from Redux DevToolswhich is helpful for debugging Redux’ “States” and “Actions” but won’t help to understand the “anatomy”.
Once installed, React Developer tools shows up inside Chrome’s JS Debugger as a tab called “React”. You simply need to open a React application and open this “React” tab to use the tool.

Anatomy: 6 Types Of Components

Now, if you inspect using React Developer Tools, you’ll realize that in a typical multi-view SPA React Redux app, we can categorize components into at least 6 different types based on their “purpose”.

  1. “Provider” component ➡ Injects “Store” to sub components
  2. “Router” & “RouterContext” component ➡ Navigation
  3. “Parent” Route component ➡ Main App-level wrapper component
  4. “Page” or “View” Route sub-component ➡ Helps organize stuff inside a single page or view.
  5. “Container” components ➡ Deals w/ Redux And “Presentational”
  6. “Presentational” components ➡Renders the HTML and Listens to Events

Let’s explore each of them one by one.

The Example App

In this blog I’ll go over the component tree or the anatomy of the first page of React Redux blog post app(live app) that I’ve been using for all my blogs.

If we draw a border against every component we code and makes up the first page(PostList) of the blog post app, it will look like below:

Note: You can click on the picture to zoom and read

Legend:

  1. The numbers represent the type of the component as mentioned above.
  2. Dotted lines = Components that are not visible. These are used for JS logic, routing, “container” components and so on.
  3. Solid RED lines = Components that are visible (i.e. has HTML w/ something to see and interact)

Let’s look at each type of component one-by-one.

1. “Provider” Component

  1. This is the top-most component of every React Redux App.
  2. Purpose: It simply provides(injects) Redux’ “Store” to all child components.
  3. It has no visible HTML.
ReactDOM.render(
<Provider store={store}>
<Router history={browserHistory} routes={routes} />
</Provider>
, document.getElementById(‘body’));

2. “Router” And “RouterContext” Component

  1. This is generated by React-Router.
  2. It is usually the child of “Provider” and the 2nd top-most component.
  3. Purpose: It is used to provide navigation between different “views” or “pages” within the app.
  4. It has no visible HTML.
  5. It also generates “RouterContext” sub component that renders “views” or “pages” based on the route.
<Router history={browserHistory} routes={routes} />

3. “Parent” Route Component

  1. This is the root (1st) component that’s rendered by React Router when the route is “/” or anything after that “/*.*” .
  2. Purpose: It is usually a dummy wrapper component that simply render child views components.
//Routes..
export default (
<Route path=”/” component={App}> <-- "Parent" Route component
<IndexRoute component={PostsIndex} /> <-- default child Route
<Route path=”posts/new” component={PostsNew} /> <-- Child Routes
<Route path=”posts/:id” component={PostsShow} />
...
</Route>
);

For example: In our app, if the route is “/”, the Router renders “App” and then “PostIndex” as “App’s” child. Similarly, if the route is: “/posts/new”, the router renders “App” and then “PostsNew” as App’s child.

export default class App extends Component {
render() {
return (
<AppContainer>
{this.props.children} <-- Render Child Views/Pages
</AppContainer>
);
}
}

4. “Pages” or “View” level Components

  1. These are dummy wrapper components and 1st child components within a given route.
  2. These are the components we pass as the “child” views to Router like: PostIndex, PostsNew etc.
  3. Purpose: They are used to organize all the components w/in a Page or View.
//Routes..
export default (
<Route path=”/” component={App}> <-- "Parent" Route component
<IndexRoute component={PostsIndex} /> <-- default child Route
<Route path=”posts/new” component={PostsNew} /> <-- Child Routes
<Route path=”posts/:id” component={PostsShow} />
...
</Route>
);

Example: PageIndex Page component

class PostsIndex extends Component {
render() {
return (
<div>
<HeaderContainer type=”posts_index”/>
<ValidateEmailAlertContainer/>
<PostsList />
</div>
);
}
}

5. “Container” Components

  1. Redux generates them as “Connect(<comp name>)” for example: “Connect(Header)”, “Connect(ValidateEmailAlert)” etc
  2. These are wrapper components that has JS logic and deals with Redux.
  3. They act like a middle man between Redux and “Presentational” components
  4. These are parent-components to “Presentational” components.
  5. There can be numerous container components per page.
Note: “Presentational” components are responsible for actually rendering HTML and then listening to user and server events but they delegate all the work to “Container” components.

6. “Presentational” Components

  1. “Presentational” components are responsible for actually rendering HTML
  2. They listen to user and server events but they delegate all the work to “Container” components.
  3. These are typically child components of “Container” components.
  4. There can be numerous “presentational” components per page.
Note: Any component that doesn’t deal with JS and simply renders something is called “Presentational” component. It doesn’t necessarily have to have a parent “Container” component.

That’s it!