Skip to content

Instantly share code, notes, and snippets.

@jawakarD
Last active March 30, 2020 07:57
Show Gist options
  • Save jawakarD/277de29aec2b0266c1e468e96a9448a9 to your computer and use it in GitHub Desktop.
Save jawakarD/277de29aec2b0266c1e468e96a9448a9 to your computer and use it in GitHub Desktop.

React Components

  1. Use stateless functions
  2. Use PureComponent
  3. Avoid manual .bind
  4. Don't use inline methods
  5. Use mapDispatchToProps
  6. Use SubComponents instead of multiple renders
  7. Should Specify defaultProps
  8. Should Specify flow Types
  9. Use redux for data
  10. pass a function to setState, to update state based on currentState

Use stateless functions

// Good
const HelloName = (props) => {
  return (
    <div>Hello {props.name}</div>
  );
}

// Bad
class HelloName extends Component {
  render() {
    return (
      <div>Hello {this.props.name}</div>
    );
  }
}

// Bad
class HelloName extends PureComponent {
  render() {
    return (
      <div>Hello {this.props.name}</div>
    );
  }
}

Use PureComponent

// Good
class HelloName extends PureComponent {
  componentDidMount() {
    this.props.fetchData(this.props.id);
  }
  render() {
    return (
      <AnotherPureComponent data={this.props.data} />
    );
  }
}

// Bad
class HelloName extends Component {
  componentDidMount() {
    this.props.fetchData(this.props.id);
  }
  render() {
    return (
      <AnotherPureComponent data={this.props.data} />
    );
  }
}

Avoid manual .bind

// Good 
class HelloName extends PureComponent { 
  handleChange = (e) => { 
    this.props.updateField(e.target); 
  } 
  render() { 
    return ( 
      <div> 
        <form> 
          <input name="name" onChange={this.handleChange} /> 
          <button type="submit" /> </form> </div> 
    ); 
  } 
} 

// Bad 
class HelloName extends PureComponent { 
  handleChange(e) { 
    this.props.updateField(e.target); 
  } 
  render() { 
    return ( 
      <div> 
        <form> 
          <input name="name" onChange={this.handleChange.bind(this)} /> 
          <button type="submit" /> 
        </form> 
     </div> 
   ); 
  } 
} 

// Bad 
class HelloName extends PureComponent { 
  handleChange(e) { 
    this.props.updateField(e.target); 
  } 
  render() { 
    return ( 
      <div> 
        <form> 
          <input name="name" onChange={(e) => this.handleChange(e)} /> 
          <button type="submit" /> 
        </form> 
      </div> 
    ); 
  } 
}

Don't use inline methods

// Good
class HelloName extends PureComponent {
  handleChange = (e) => {
    this.props.updateField(e.target);
  }

  render() {
    return (
      <div>
        <form>
          <input name="name" onChange={this.handleChange} />
          <button type="submit" />
        </form>
      </div>
    );
  }
}

// Bad
class HelloName extends PureComponent {
  render() {
    return (
      <div>
        <form>
          <input name="name" onChange={(e) => this.props.updateField(e.target)} />
          <button type="submit" />
        </form>
      </div>
    );
  }
}

Use mapDispatchToProps

// Good
import { updateField } from './actions';

class HelloName extends PureComponent {
  handleChange = (e) => {
    this.props.updateField(e.target);
  }

  render() {
    return (
      <div>
        <form>
          <input name="name" onChange={this.handleChange} />
          <button type="submit" />
        </form>
      </div>
    );
  }
}

export default connect({}, { updateField })(HelloName);

// Bad
class HelloName extends PureComponent {
  handleChange(e) {
    this.props.dispatch(this.props.updateField(e.target));
  }

  render() {
    return (
      <div>
        <form>
          <input name="name" onChange={this.handleChange.bind(this)} />
          <button type="submit" />
        </form>
      </div>
    );
  }
}

export default connect()(HelloName);

Use SubComponents instead of multiple renders

// Good
const AnotherComponent = () => {
  return (<div>AnotherComponent</div>);
}

class HelloName extends PureComponent {
  componentDidMount() {
    this.props.fetchData(this.props.id);
  }
  render() {
    return (
      <div>
        <AnotherComponent />
      </div>
    );
  }
}

// Bad
class HelloName extends PureComponent {
  componentDidMount() {
    this.props.fetchData(this.props.id);
  }
  
  renderAnother() {
    return <div>AnotherComponent</div>;
  }

  render() {
    return (
      <div>
        {this.renderAnother()}
      </div>
    );
  }
}

Should Specify defaultProps

// Good
const HelloName = ({ haveSecondChild }) => {
  return (
    <div>
      <FirstChild />
      {haveSecondChild && <SecondChild />}
    </div>
  )
};

HelloName.defaultProps = {
  haveSecondChild: false,
};

// Bad
const HelloName = ({ haveSecondChild }) => {
  return (
    <div>
      <FirstChild />
      {haveSecondChild && <SecondChild />}
    </div>
  )
};

// Bad
const HelloName = ({ haveSecondChild = false }) => {
  return (
    <div>
      <FirstChild />
      {haveSecondChild && <SecondChild />}
    </div>
  )
};

Should Specify flow Types

type Props = {
  haveSecondChild: boolean
}
// Good
const HelloName = ({ haveSecondChild }: Props) => {
  return (
    <div>
      <FirstChild />
      {haveSecondChild && <SecondChild />}
    </div>
  )
};

// Bad
const HelloName = ({ haveSecondChild }) => {
  return (
    <div>
      <FirstChild />
      {haveSecondChild && <SecondChild />}
    </div>
  )
};

Use redux for data

// Good
class TestComponent extends PureComponent {
  handleChange(e) {
    this.props.updateField(e.target);
  }

  handleSubmit() {
    this.props.saveData();
  }

  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <input name="name" onChange={this.handleChange} />
          <button type="submit" />
        </form>
      </div>
    )
  }
};

// Bad
class TestComponent extends PureComponent {
  constructor() {
    super();
    
    this.state = {
      fields: {};
    }
  }

  handleChange(e) {
    const fields = Object.assign({}, this.state.fields};
    fields[e.target.name] = e.target.value;

    this.setState({
      fields,
    });
  }

  handleSubmit() {
    this.props.saveData(this.state.fields);
  }

  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <input name="name" onChange={this.handleChange} />
          <button type="submit" />
        </form>
      </div>
    )
  }
};

pass a function to setState, to update state based on currentState

// Good
class TestComponent extends PureComponent {
  constructor() {
    super();
    
    this.state = {
      loading: false;
    }
  }

  toggleLoading() {
    this.setState((prevState) => {
      loading: !prevState.loading
    });
  }

  // render method
};

// Bad
class TestComponent extends PureComponent {
  // constructor

  toggleLoading() {
    this.setState({
      loading: !this.state.loading
    });
  }

  // render method
};

Components

  • No index.js or index.jsx for filename Eg: Dashboard/Dashboard.jsx
  • component filename should be in Pascal case Eg: FileName.jsx
  • No nested Folders
  • Foldername should be in Pascal case. Eg: Dashboard/

Types

  • All Types goes into types folder
  • Filename should be in lowerCamelCase and append Types to it. Eg: types/reduxTypes.js
  • should be .js extension.

Actions

  • All Actions goes into actions folder
  • Filename should be in lowerCamelCase and append Actions to it. Eg: actions/reduxActions.js
  • should be .js extension.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment