High level view and logic separation in React

Posted on February 17th, 2019

One of React’s greatest strengths is the ability to separate the view from the logic. I like to take it a step further and create two separated components, one harboring view, and one – logic.

On the first sight, this might sound like an overhead. Why should I create two files, when I can just utilize render method. While true, this approach has many benefits. For starters, it allows two people to work on one thing simultaneously. One, a junior, can write styles and JSX markup, while a more experienced developer can write its logic handling. Another valid point is a separation of concerns – an entire view can be replaced without even touching the files with logic inside, as long as they use the same props.

So, how do I approach such thing? Simple, really.

First thing is, I define the state. The component should things, like – respond to mouse hover, distinguish its state between active and dormant and display text passed to it. Next, I write the logic. Most often this is a class with some internal methods:

// containers/Thing/index.js

import View from "@src/ui/Thing";

class Thing extends React.Component {
  state = {
    active: false,
    hovered: false,
  };
  
  setActiveState = () => this.setState({ active: !this.state.active });
  
  setHoveredState = () => this.setState({ hovered: !this.state.hovered });
  
  render() {
    return (
      <View
        active={this.state.active}
        hovered={this.state.hovered}
        onClick={this.setActiveState}
        onMouseEnter={this.setHoveredState}
        onMouseLeave={this.setHoveredState}
        text={this.props.text}
      />
    );
  }
}

So much for logic. There can be a lot more, of course, but for the sake of illustration, it will suffice.

Next, the view.

// ui/Thing/index.js

const Thing = (props) => {
  const {
    active,
    hovered,
    onClick,
    onMouseEnter,
    onMouseLeave,
    text,
  } = props;
  
  return (
    <div
      onClick={onClick}
      onMouseEnter={onMouseEnter}
      onMouseLeave={onMouseLeave}
      style={{
        background: active ? "tomato" : "transparent",
        color: hovered ? "yellow" : "black",
      }}
    >
      {text}
    </div>
  );
};

Again, this is it. Very simple and concise.

This pattern works great in teams with junior and middle developers, as they can work on the target goal while not staying behind due to either lack of knowledge in more complex logic matters, or to lack of interest in writing views.

  • A minimal example can be seen on CodeSandbox;
  • Full example of this architecture can be found in my project.

(c) 2022 buszewski.com — All rights reserved. This site probably harvests your cookies.