Is conditionally rendering react child components a violation of SRP?

799 views Asked by At

I'm fairly new to React and OOD so bear with me. Ideally I want to write my application in such a way that it will be easy to reason about and scale well. Rather, make my code as S.O.L.I.D as possible. I'm also concerned about testing my components as I'm new to TDD, as well.

So for example I've already tried writing my code very similar to this:

App.jsx - First Trial

// all other code omitted

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      roundScore: 0, 
      lives: 1,
      modal: true, 
    };
  }

  render() {
    return (
      <div className="App">
        <Header 
          modal={this.state.modal} 
          lives={this.state.lives} 
          score={this.state.score} 
        />
      </div>
      );
  }
}

Header.jsx - First Trial

const Header = function(props) {
  if (props.modal) {
    return (<Logo logo={logo} />);
  } else {
    return (
      <div>
        <Lives lives={props.lives} />
        <Score score={props.score} />
      </div>
      );
  }
};

const Logo = function(props) {
  return (
    <div>
      <img
        src={props.logo}
        className="logo logo--xs"
        alt="logo"
      />
    </div>
    );
};

const Score = function(props) {
  const text = (props.text ? <strong>{props.text}</strong> : '');
  return (
    <p className={props.styles}>
      {text}
      {props.score} pts
    </p>
    );
};

const Lives = function(props) {
  return (
    <p className="lives lives--left">
      Lives:
      {props.lives}
    </p>
    );
};

export default Header;

The reason I initially setup my code like this was because I had a lot of components and the App.jsx file and wanted to pull some of them out and nest them in wrapper components like <Header /> <Body /> <Footer />.

I began writing some unit tests with Jest and Enzyme for the above mentioned and found that I was having some difficulty testing some of the components in isolation. For example, testing the <Score /> component proved difficult unless I changed my export statement to something like export { Header, Scores, Lives, Logo }; but that doesn't seem like something I should do just for testing?

On top of that I have some propTypes which are required on these components so shallow rendering the <Header /> component and then passing props to <Score /> just to avoid the warnings in my console didn't seem right to me.

So instead I modified my code to the following:

App.jsx - Second Trial

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      roundScore: 0, 
      lives: 1,
      modal: true, 
    };
  }

  render() {
    return (
      <div className="App">
        <Logo modal={this.state.modal} logo={logo} />
        <Lives modal={this.state.modal} lives={this.state.lives} />
        <Score modal={this.state.modal} score={this.state.roundScore} />
      </div>
      );
  }
}

Header.jsx - Second Trial

const Logo = function(props) {
  const styles = (props.modal ? 'logo logo--xs' : 'hide'); 
  return (
    <div>
      <img
        src={props.logo}
        className={styles}
        alt="I-Spell-Its logo"
      />
    </div>
    );
};

const Score = function(props) {
  const styles = (props.modal ? 'hide' : props.styles)
  const text = (props.text ? <strong>{props.text}</strong> : '');
  return (
    <p className={styles}>
      {text}
      {props.score} pts
    </p>
    );
};

const Lives = function(props) {
  const styles = (props.modal ? 'hide' : 'lives lives--left')
  return (
    <p className={styles}>
      Lives:
      {props.lives}
    </p>
    );
};

export { Score, Logo, Lives };

Already I've found this setup easier to test, however now I have a few concerns:

  1. Is it okay to use CSS to hide components depending on the application state? Will I be taking any performance hits?
  2. I have several other parent/wrapper components that conditionally render child components depending on state and I feel it will be very difficult (but not impossible) to rewrite a lot of them. Should I bother or accept my mistakes and avoid this next time around?
  3. Ultimately, I'm curious to know if conditionally rendering child components is a violation of Single Responsibility Principle?

Please don't flag this as a question that provokes discussion or opinions. I have done my research; I have read 3 books on React, taken one online course and read several articles and style guides, but I still have difficulty wrapping my head around how to best structure react applications. It would be nice to hear from some of the more experienced members of the community.

0

There are 0 answers