Skip to content

Instantly share code, notes, and snippets.

@RebootJeff
Last active June 20, 2017 21:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RebootJeff/125fa7ebb9d440e07a3a3602e3ef64db to your computer and use it in GitHub Desktop.
Save RebootJeff/125fa7ebb9d440e07a3a3602e3ef64db to your computer and use it in GitHub Desktop.
rendering different message "things"
.foo {
margin: 10px;
}
.banner {
padding: 10px;
text-align: center;
}
.error {
background-color: red;
}
.warning {
background-color: yellow;
}
.confirmation {
background-color: green;
}
// Consider making this a functional component unless you really need it to be a class component
class Foo extends Component {
render() {
let type;
let message;
if(error) {
type = 'error';
message = error.message;
} else if(1 === 2) {
type = 'warning';
message = 'Something REALLY weird is happening?!';
} else {
type = 'confirmation';
message = 'Your dog was succesfully fed through our app';
}
return (<div className="foo">
<Banner type={type}>{message}</Banner>
{/* ...and other stuff to render within the same div.foo */}
</div>);
}
}
// Hi! I'm a "functional component" because I'm just a function that happens to accept `props` and return some JSX.
const Banner = (props) => {
const { type, message } = props;
return (<div className={'banner ' + type}> // the type helps defines the styling via CSS
<h2>{message}</h2>
</div>);
};
@ksarnasaurus
Copy link

There's a lot more to the class than I described to you. I'm not writing it, I'm fixing a bug in it and trying to address style comments in my PR review.

  • Line 5 is helpful. In a case like this, I wasn't sure whether to use let at the beginning or const in each if block.
  • This is basically what the code currently looks like. My coworker wants to "bail early on special cases", which is generally a good idea. His example:
 return <error div>
}
if (< empty options>) {
 return < empty options div>
}
# now we know all assumptions are met
<build form>
return <form>
  • "functional component" - when should I use these vs. making it a class component?

@RebootJeff
Copy link
Author

RebootJeff commented Jun 20, 2017

Line 5 is helpful. In a case like this, I wasn't sure whether to use let at the beginning or const in each if block.

const in each if block wouldn't actually work. Both const and let are block-scoped whereas var is function-scoped (lexical). In other words, you have no choice 😝

This is basically what the code currently looks like.

Ok that's fine. But creating the 3 different possible views should be done with separate functions (ideally 3 different React components) or separate methods (see below).

// option 1 (cleaner)
render() {
  if(/* error */) {
    return <ErrorMessage error={error} />;
  }
  if(/* special case */) {
    return <SpecialCaseComponent />;
  }

  return (
    // the form
  );
}

// option 2 (faster, but file length grows quickly)
_renderError(error) {
  // has access to `this.props` and `this.state`
  // returns some JSX
}
_renderSpecial() {
  // ...
}
_renderForm() {
  // ...
}
render() {
  if(/* error */) {
    return this._renderError(error);
  }
  if(/* special case */) {
    return this._renderSpecial();
  }

  return this._renderForm();
}

when should I use these vs. making it a class component?

Functional components are dead simple functions that have access to React component props and nothing else. You usually use them to create "dumb/presentational components" that have no major logic. You give them click handlers, data to render, etc as props. But they don't define their own event handlers and whatnot.

Class components have access to props, state, React lifecycle methods such as componentDidMount, refs, etc. They are more powerful. You usually use them to create "smart/stateful containers". If you use Redux, then class components are the ones that actually get wired up with Redux stuff. As the term "smart container" implies, they often define event handlers, interact with Redux state/actions (or normal React state if you have no state management library like Redux), etc. They often render functional components rather than directly rendering any HTML themselves (except for maybe wrapping <div>s because every React component must return a single node, so you might have to wrap stuff into a single <div>).

If using the classic MVC paradigm... you can kinda think of class components as being controllers, but frameworks like React prefer to avoid analogies to MVC altogether. It's a whole new world!

Guideline: Use functional components as much as possible. Only use class components if you need to access this.state, lifecycle methods, etc. When using class components, try to have them render as little HTML as possible by having them render functional components. The functional components then handle the nitty gritty of HTML. Of course functional components can render more React components as children, but the point is that "smart containers" aren't concerned with presentation so much as they are concerned with wiring up events, actions, state, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment