React(.js)ing to My New Foster Kittens: A React/Redux Application
Taylor Sieling
Posted on June 7, 2021
The Project
All of my Flatiron School projects have related to my interests and passions, and my React.js project is probably closest to my heart. I have recently started fostering kittens through my local Humane Society, and as such built an application to manage kitten intakes and updates. Users can input all pertinent intake information when getting new fosters, and edit/delete the information as necessary.
The Structure
Routes
/
/kittens
/kittens/:id
/kittens/:id/edit
/kittens/intake
Presentational Components
Home.js
Navigation.js
Footer.js
KittenCard.js - for the Kitten Index page
KittenShow.js - for the Kitten Show page
Container Components
Kittens.js - for the Kitten Index page
KittenContainer.js - for the Kitten Show page
IntakeForm.js - new Kitten form
EditForm.js - edit Kitten form
The Rails API Backend
I set up my Model and Controller using the Rails resource generator. I created my seeds, enabled CORS, and set-up my JSON serializer.
The React.js Frontend
I used create-react-app
to get started with my frontend. I set-up my folders for Containers, Components, Actions, and Reducers.
Using Redux
Although React Hooks are replacing Redux, I appreciated getting to learn the Redux pattern. Redux lets you create a store to hold your state. The store can dispatch an action to the appropriate reducer and create an object to make changes to the state. Components are then able to re-render on the DOM with the new data.
I used my Redux store to hold information about my kittens, which could be passed to my Presentational Components. My Presentational Components are stateless and accept props mapped from their Container Component's state. I used Functional Components within my Presentation Components.
My Container Components, which needed access to my Redux store and certain Lifecycle Methods, were build using Class Components.
Redux-Thunk Middleware
Javascript web requests are asynchronous, meaning our fetch requests can run into an issue where our action creator returns an action before the API data is actually fetched.
The Thunk middleware allows us to return a function inside of the action creator, rather than a Javascript object. That function can dispatch multiple actions, depending on whether the loading state is true or false.
Here is an example of the Redux-Thunk middleware in action:
// src/containers/KittenContainer.js
class KittenContainer extends Component {
componentDidMount() {
this.props.fetchKittens();
}
...
}
I call my fetchKittens()
method in my componentDidMount()
lifecycle method.
// src/actions/kittens.js
export const fetchKittens = () => {
return (dispatch) => {
dispatch({ type: "LOADING_KITTENS"})
fetch('http://localhost:3001/kittens')
.then(res => res.json())
.then(kittens => {
console.log('fetching kittens')
dispatch({
type: "KITTENS_LOADED",
payload: kittens
})
})
}
}
I pass the dispatch method (from the store) into my returned function, and call dispatch twice in the function's body. The first dispatch indicates that I am loading the kitten data from my API. The second dispatch makes the actual GET request to the server.
// src/reducers/kittenReducer.js
const kittens = (state = { kittens: [], loading: false}, action) => {
switch(action.type){
case "LOADING_KITTENS":
return {
...state,
loading: true
}
case "KITTENS_LOADED":
return {
...state,
kittens: action.payload,
loading: false
}
...
Here you can see my case switches in my kittenReducer.js
.
// src/containers/KittenContainer.js
handleLoading = () => {
if (this.props.loading) {
return (
<div>
<div className="kittens">
<div className="home-text">
<h1>Knittin' Kitten Foster</h1>
</div>
</div>
<div><h2>Grabbing the precious baby... one moment please!</h2></div>
</div>
)
} else {
const kitten = this.props.kittens.find(kit => kit.id === parseInt(this.props.match.params.id))
return (
<>
<div className="kittens">
<div className="home-text">
<h1>{kitten.name}</h1>
</div>
</div>
<KittenShow kitten={kitten} handleDeleteClick={this.handleDelete}/>
</>
)
}
}
render() {
return (
<div>
{this.handleLoading()}
</div>
)
}
Back in my KittenContainer.js
, I wrote a method called handleLoading()
which gives the user a loading message while the kittens are being fetched from the server.
In Conclusion
This project saw many iterations in my head. There is still a lot more that I would like to implement in the future - such as authorization for user accounts, an adoption application for community members to apply to adopt specific kittens, etc.
I have really enjoyed learning React and hope to find a job as a front-end developer in the future.
Posted on June 7, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.