Skip to content

Instantly share code, notes, and snippets.

@chadwithuhc
Last active February 7, 2018 00:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chadwithuhc/4c0ae8a15891e3be3570fbf6efcf2e61 to your computer and use it in GitHub Desktop.
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
Copy link

justsml commented Feb 6, 2018

Great work Cheddar!!!

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