Skip to content

Instantly share code, notes, and snippets.

@chadwithuhc
Last active February 7, 2018 00:05
Show Gist options
  • Select an option

  • Save chadwithuhc/4c0ae8a15891e3be3570fbf6efcf2e61 to your computer and use it in GitHub Desktop.

Select an option

Save chadwithuhc/4c0ae8a15891e3be3570fbf6efcf2e61 to your computer and use it in GitHub Desktop.
React Refactors for Clean Code
// Challenge: Refactor the `render()` method with declare all variables at top
render() {
return (
<li>
<div className="profile-card">
<header className="profile-header" onClick={this.toggleClass}>
<img src={this.props.profile.image} alt={this.props.profile.name} />
<h2>{this.props.profile.name}</h2>
</header>
<section
className={
this.state.active ? "skills-container hidden" : "skills-container"
}
>
<h4>Skills</h4>
<ul className="skills-list">
{this.props.profile.skills.map(skill => {
return <li key={skill}>{skill}</li>
})}
</ul>
</section>
</div>
</li>
)
}
// Refactors to ->
// 1. Replace all `this.props.profile` instances to be just `profile` to allow for readability
// We use destructuring to accomplish this
// Now we know where the `profile` is coming from when we are referring to it
// 2. Replace the full `this.state.active` with the destructured value
// If we need to refactor to swap some props for state, we only change it in one place
render() {
const { profile } = this.props
const { active } = this.state
return (
<li>
<div className="profile-card">
<header className="profile-header" onClick={this.toggleClass}>
<img src={profile.image} alt={profile.name} />
<h2>{profile.name}</h2>
</header>
<section
className={
active ? "skills-container hidden" : "skills-container"
}
>
<h4>Skills</h4>
<ul className="skills-list">
{profile.skills.map(skill => {
return <li key={skill}>{skill}</li>
})}
</ul>
</section>
</div>
</li>
)
}
// Challenge: We're try to leave the `constructor()` out since we can achieve the same result with syntactical sugar
export class ProfileCard extends React.Component {
constructor(props) {
super(props)
this.state = {
active: true
}
this.toggleClass = this.toggleClass.bind(this)
}
toggleClass() {
var currentState = this.state.active
this.setState({ active: !currentState })
}
// ...
}
// Reactors to ->
// 1. Move `state` to a property on the Class
// 2. Bind `this` with the syntactical sugar available, setting `toggleClass` to an anonymous function with `this` bound
export class ProfileCard extends React.Component {
state = {
active: true
}
toggleClass = () => {
var currentState = this.state.active
this.setState({ active: !currentState })
}
// ...
}
// Challenge: Refactor using ES6 shorthand syntax
componentDidMount() {
fetch("./dinosaurs.json")
.then(res => res.json())
.then(res =>
this.setState({
profiles: res
})
)
}
// Refactors to ->
// 1. By renaming the arugment in the second `.then()`, we can pass it along directly to `this.setState()`
componentDidMount() {
fetch("./dinosaurs.json")
.then(res => res.json())
.then(profiles =>
this.setState({
profiles
})
)
}
// 2. We could also condense it more if we'd like
componentDidMount() {
fetch("./dinosaurs.json")
.then(res => res.json())
.then(profiles => this.setState({ profiles }))
}
// Challenge: Remove calls to `.querySelector()`
export class InputForm extends React.Component {
submitHandler(event) {
event.preventDefault()
const textareaValue = document.querySelector('#application-text').value
console.log(textareaValue)
}
render() {
return (
<form id="application-input" onSubmit={this.submitHandler}>
<label>Apply Here: </label>
<textarea id="application-text" rows="8" cols="100" />
<input id="submit" type="submit" value="Submit" />
</form>
)
}
}
// Refactors to ->
// 1. Add `ref="appText"` to the textarea element. We can access refs on `this.refs.x`
// 2. Convert the `document.querySelector()` to be `this.refs.appText` instead, which will be equal to the DOM node
// 3. Since we are now using `this` inside our `submitHandler()` we need to bind the function with shorthand syntax
export class InputForm extends React.Component {
submitHandler = (event) => {
event.preventDefault()
const textareaValue = this.refs.appText.value
console.log(textareaValue)
}
render() {
return (
<form id="application-input" onSubmit={this.submitHandler}>
<label>Apply Here: </label>
<textarea ref="appText" id="application-text" rows="8" cols="100" />
<input id="submit" type="submit" value="Submit" />
</form>
)
}
}
// Challenge: Refactor for readability and testability
export class SkillList extends React.Component {
render() {
return (
<ul className="skills-list">
{this.props.dinosaurs.skills.map(item => <li key={item}>{item}</li>)}
</ul>
)
}
}
// Refactors to ->
// 1. We move the list item to it's own render method, naming it with `render...` to hint it's returning JSX
// This allows the `renderListItem()` method to be tested on it's own
// When your code becomes larger, this pattern will be easier to read
export class SkillList extends React.Component {
renderListItem(item) {
return <li key={item}>{item}</li>
}
render() {
return (
<ul className="skills-list">
{this.props.dinosaurs.skills.map(this.renderListItem)}
</ul>
)
}
}
@justsml

justsml commented Feb 6, 2018

Copy link
Copy Markdown

Great work Cheddar!!!

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