React is only the ‘V’ part of MVC and as such is not opinionated in how you architect your UI.

If proper attention is not given, a reasonably large react app can quickly succumb to a mess of stateful components, each with a mind of it’s own, quickly violating the react way of doing things.

There are several key points one must keep in mind while building with React:

Stateless components Composition Centralised state management with Redux

Stateless components

Your components must be as stateless as possible; as in, your components should not run it’s own state, instead depend on passed in props.

This makes your components predictable and easily testable as they behave like pure functions. Ingest data and spit out JSX.

Composition

This is a two part approach:

Breaking down a complex component into smaller manageable bits Composing a complex UI from common custom components

Breaking down a complex component into smaller manageable bits

Say you have a component as this:

This is not exactly clear from a bird’s eye view. Too many divs with class names.

Also, if we have to render a different chat bubble for maybe system messages with a similar footer, we cannot. Is is all tightly coupled.

And to top it all off, this is how we use the above component:

<ChatBubble

sentBy={message.sentBy}

messageContent={message.content}

time={message.time}/>

Any updates to the chat bubble header, we have to mess around with the entire component file.

Without updating our usage, we can simply break down ChatBubble like this:

The Header & Footer can be in it’s own file and imported here. But a quick look at ChatBubble and we can see that the change now makes it much more readable.

We know there is a header and footer part to it. So far so good.

Composing a complex UI from common custom components

Now say we have two kinds of messages: one that users send each other as text. Others that includes a gallery of images. All other details, like header & footer stay same.

With our current implementation, it is significantly difficult.

We could write complex logic to understand whether messageContent includes images and split them and perform all sorts of dark magic to get it to work.

Or maybe we could do something like this:

Check out the body section. We did {props.children} . It means any child of the component is passed in here.

And at the call site, do this:

Now, we can render chat messages as we see fit.

Tomorrow, when there is a third kind of chat message from maybe a bot while header and footer remain same, we simply update the way the body content is rendered from the component that is using ChatBubble .

Code re-used :)

Centralised state management with Redux

Redux makes our application state predictable by keeping it in a central location/repository.

Only way to update the state is to issue actions which are of the format:

{

type: String,

payload: Any

}

Example:

{

type: 'SET_USER_DETAILS',

payload: {

user: {

_id: 1,

name: 'John Doe'

}

}

}

These actions are passed into pure functions called reducers who consume the action and returns a new version of state. This is then persisted in the store and all the functions subscribing to that part of the state tree are notified.

Example UsersReducer.js

This data can be consumed by UI like this:

Every time the store value changes, the User component will receive updates.

Learn about redux from this egghead course by Dan Abramov.