Skip to content

Instantly share code, notes, and snippets.

@joshuajhun
Last active January 24, 2019 23:21
Show Gist options
  • Save joshuajhun/443196a3989d7171a9515ca691511588 to your computer and use it in GitHub Desktop.
Save joshuajhun/443196a3989d7171a9515ca691511588 to your computer and use it in GitHub Desktop.

Components

Components in our application is broken into 4 major types: elements, blocks, decorators, and containers.

Elements

Elements are the smallest of the bunch and are considered the building blocks of our application. The goal being that they make up the base of our component hierarchy. It's easier and scalable if our component hierarchy is built upon these reusable, highly maluable pieces. If we our baseline elements are unoppinionated, pure, stateless, functional components then it makes extending upwards a lot easier.

What are Elements?

Ultimately are components that just return jsx.

const TextInput = ({ value, handleChange, name }) => (
  <input 
    type="text"
    value={value} 
    onChange={handleChange} 
    name={name} 
  />
)

Whats nice about these components is that they will always be that particular input regardless of where you put them or place them. They also have the added beneifit of cleaning up our API making things a lot easier to read in the long run.

Blocks

Blocks like the name suggest are UI componets comprised of smaller element compents. At their core they should have no logic. Like the elements they should simply return JSX. Any logic, mapping, etc should be moved out of this component. It can receive props but it's main job is to simply be a composition of elements

Component

import React from 'react';
import { TextInput, Button } from '../../elements';

const VerificationForm = ({ handleChange, handleSubmit, verification }) => {
  return (
    <form onSubmit={handleSubmit}>
      <TextInput value={verification} handleChange={handleChange} name="verification" />
      <Button value="Verify" />
    </form>
  );
};

Component API

import { VerificationForm } from '../../blocks';

class BankVerification extends Component {
	...
  render () {
    <VerificationForm  
      handleChange={this.handleChange}
      handleSumbit={this.handleSubmit}
      verification={this.state.verification} 
    />
  } 
}

Notice that this block is essentially comprised of the small building blocks. The intent being if something were to change on the element level that change is then effected across the board instead of going through component by component. The point of the abstraction is for readibility and to seperate concerns.

Decorators

Decorators can be any type of component (functional, stateful, class based, etc). The main thing that set's these components apart are the fact that they contain some sort of logic. They are either keeping track of state, itterating over a collection, or rendering other blocks. It should rarely render elements but we understand that there are times when that is a better solution. The relationship between decorator and block should be one that encourages a slim render function.

import React, { Component } from 'react';
import { VerificationForm } from '../../blocks';

class BankVerification extends Component {
  state = {
    verification: ''
  };

  handleSubmit = event => {
    event.preventDefault();
    const { handleVerification, bankAccountId } = this.props;
    const { verification } = this.state.verification
    handleVerification({ verification, bankAccountId });
  };

  handleChange = ({ target: { value: verification } }) => this.setState({ verification });

  render() {
    
    return (
      <section style={this.props.style}>
        <VerificationForm
          handleChange={this.handleChange}
          handleSubmit={this.handleSubmit}
          {...this.state}
        />
      </section>
    );
  }
}

export default BankVerification;

Containers

Containers are components that are connected to Apollo. They should handle mutations, queries, and errors. Their primary purpose is to feed the decorators with the necessary props to function. They can be stateful components but should lean towards being a provider of props to keep testing really easy. The point of this is to make sure props sent down correctly.

import React, { Component } from 'react';
import { graphql } from 'react-apollo';
import { VERIFY_BANK_ACCOUNT } from '../../../queries';
import { BankVerification } from '../../decorators';

class BankVerificationContainer extends Component {
  handleVerification = variables => {
    const { verifyBankAccount } = this.props;
    verifyBankAccount({ variables });
  };

  render() {
    const { style } = this.props;
    
    return (
      <BankVerification
        style={style}
        handleVerification={this.handleVerification}
        {...this.props}
      />
    );
  }
}
const verifyAccount = graphql(VERIFY_BANK_ACCOUNT, { name: 'verifyBankAccount' });

export default verifyAccount(BankVerificationContainer);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment