Skip to content

Instantly share code, notes, and snippets.

@andrewhl
Created April 25, 2018 13:03
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 andrewhl/49381809fd9293c0b55fb4313f6d659c to your computer and use it in GitHub Desktop.
Save andrewhl/49381809fd9293c0b55fb4313f6d659c to your computer and use it in GitHub Desktop.
import React, { Component } from 'react';
// Best practice is to use prop-type declarations on all components that receive props.
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom'
import { connect } from 'react-redux'
import { Table, Button, Container, Input, Form } from 'semantic-ui-react';
import RequestRegistryRow from '../components/RequestRegistryRow';
import Layout from '../components/Layout';
class Registry extends Component {
static propTypes = {
fetchData: PropTypes.object.isRequired
}
// If you're using ES6 syntax, constructor functions are unnecessary in most situations.
// See next comment about method bindings.
// constructor(props) {
// super(props);
// this.onChange = this.onChange.bind(this)
// this.onClear = this.onClear.bind(this)
// this.onSubmit = this.onSubmit.bind(this)
// }
// Method bindings are unnecessary with ES6. You can use the arrow syntax instead. It binds this to the current context.
onChange = (e) =>
{
// if(e.target.value ===""){
// this.props.fetchData({firstName: "*"})
// }
// else {
// this.props.fetchData({firstName: e.target.value})
// }
// This conditional can be simplified by returning the method:
// if(e.target.value ===""){
// return this.props.fetchData({firstName: "*"})
// }
// return this.props.fetchData({firstName: e.target.value})
// It's generally good practice to always return something.
// My preference would be to simplify it even more using a ternary expression:
const firstName = (e.target.value === "") ? "*" : e.target.value;
// This uses ES6 object shorthand, equivalent to: {firstName: firstName}
return this.props.fetchData({firstName});
}
onClear = (e) =>
{
let searchInput = ReactDOM.findDOMNode(this.refs.searchInput)
// In React, try to avoid mutating values by reassignment.
// This is an anti-pattern.
// This is a good indication of state that should be stored either in local state, and modified using
// this.setState(), or in a redux reducer. If you find yourself mutating objects, it should be a red
// flag that you need to rethink your data structure. This sort of thing can lead to a lot of bugs in the future.
searchInput.value=""
this.props.fetchData({firstName: "*"})
}
onSubmit = (e) =>
{
//prevents full page reload
e.preventDefault();
}
// You can simplify this expression by returning the component directly.
renderTitleAndForm(){
// let titleAndForm = (
return (
<Layout>
<Container>
<div>
<h2>Shareholder Registry</h2>
</div>
<div>
<h3> Filter Entries by Name</h3>
</div>
<div>
<Form onSubmit={this.onSubmit}>
<Input type="search" name="search" id="searchInput" placeholder="First Name" onChange={this.onChange} />
{' '}
<Button className ="btn-ll5" color="teal" basic onClick={this.onClear}>
Clear
</Button>
</Form>
</div>
</Container>
</Layout>
);
// return titleAndForm;
}
// I would extract this form into its own component.
// In general, connected components are 'Brains', aka 'Smart Components'. They generally concern themselves with state
// and some presentational logic, and error handling, but not so much with pure presentation. The convention is to
// pass props down from a 'Smart Component' into 'Dumb Components', responsible for purely rendering content.
// Forms are tricky because they are responsible for interactions, so I tend to make Form components connected in their own right.
// Check out: [react-redux-form](https://github.com/davidkpiano/react-redux-form), for an excellent redux form library.
renderFullForm(){
const { Header, Row, HeaderCell, Body } = Table;
// let fullForm = (
// Simplify. Unnecessary variable assignment.
return (
<Layout>
<Container>
<div>
<h2>Shareholder Registry</h2>
</div>
<h3>Filter Entries By Name</h3>
<Form onSubmit={this.onSubmit}>
<div>
<div>
<Input type="search" name="search" id="searchInput" placeholder="Filter by First Name" onChange={this.onChange} />
{' '}
<Button color="blue" basic onClick={this.onClear} style={{ marginBottom: 10 }}>
Clear
</Button>
<a>
<Button primary floated="right">
Add Transaction
</Button>
</a>
</div>
</div>
</Form>
<Table>
<Header>
<Table.Row>
<HeaderCell>Trans ID</HeaderCell>
<HeaderCell>First Name</HeaderCell>
<HeaderCell>Last Name</HeaderCell>
<HeaderCell>email</HeaderCell>
<HeaderCell>Transaction Date</HeaderCell>
<HeaderCell>Share Qty</HeaderCell>
<HeaderCell>Share Price</HeaderCell>
<HeaderCell> </HeaderCell>
</Table.Row>
</Header>
<Body>{this.renderRows()}</Body>
</Table>
</Container>
</Layout>
);
// return fullForm;
}
renderRows() {
return this.props.searchData.map((searchData, index) => {
return (
<RequestRegistryRow
key={searchData.registryid}
searchData={searchData}
/>
);
});
}
// Unnecessary else condition.
render() {
// if( this.props.searchData.length !== 0){
// return (
// this.renderFullForm()
// );
// }else{
// return (
// this.renderTitleAndForm()
// );
// }
// }
// This is how I like to format if expressions. You might look into using Prettier for
// automatic code formatting. It integrates with VSCode very nicely. Also works with WebStorm.
// Auto formats on save.
if (this.props.searchData.length !== 0) {
// Don't need to wrap return statements in () for single lines.
return this.renderFullForm();
}
return this.renderTitleAndForm();
}
// Capitalize 'To'.
// function mapStatetoProps(state){
// return {
// searchData: state.searchData
// }
// }
// Also, best practice is to write mapStateToProps in this way:
const mapStateToProps = (state) => ({
searchData: state.searchData
})
// function mapDispatchToProps(dispatch){
// return {
// fetchData: firstName => dispatch({type: 'FETCH_SEARCH_DATA', payload:firstName}),
// }
// }
// There's a nice shorthand for mapDispatchToProps. The assumption is, of course, that you'll define
// `fetchData` in an external actions file somewhere and import it.
const fetchData = (firstName) => ({type: 'FETCH_SEARCH_DATA', payload: firstName});
const mapDispatchToProps = {
fetchData
}
// There's a free video from Dan Abramov, creator of Redux, on this syntax:
// [javascript-redux-using-mapdispatchtoprops-shorthand-notation](https://egghead.io/lessons/javascript-redux-using-mapdispatchtoprops-shorthand-notation)
// In fact, there's two free courses from him on Redux, on Egghead. I highly recommend checking them out.
// Simplify:
// const ConnectedRegistry = connect(mapStateToProps, mapDispatchToProps)(Registry)
// export default ConnectedRegistry
// To:
export default connect(mapStateToProps, mapDispatchToProps)(Registry);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment