How to: Update Action With ReactJS/Redux and Rails

Aysan Isayo
The Startup
Published in
3 min readSep 23, 2020

Implementing the ability to update with React while handling Redux and a Rails API will require a few different moving pieces. This can get messy and complicated so this was my way of simplifying the process.

Goal: 1. Render two separate forms for the create/edit actions 2. When the edit button is clicked, render the edit form with pre-filled input fields that would reflect the selected object’s data. 3. Make a call to the reducer to update the object in the store state. 4. Persist updates to Rails database

Part 1.

I created two separate components, CreateStudentForm and EditStudentForm . Both components initialize local state properties used to control the value of input fields by updating state during an onChange event.

Note: This component is connected to the Redux store and utilizes the createStudent action that is made available as a prop through mapDispatchToProps. The CreateStudentForm is a simple React form that allows users to create new student objects.

The EditStudentForm component looks like:

There is more to be added to this component in order to handle an update submission, so this component is not yet completed.

Inside a StudentCard component, I added an edit button to each student object. This component is responsible for rendering individual student object data which makes it a great place to house any buttons or functionality pertaining to one object.

The handleEdit() method being called in the onClick event is being passed down from the Students container as a prop. handleEdit() accepts student as a parameter and and sets the state property, studentId to the student’s id. This property will be used inside the Students component render method to determine which of the two forms will render, create or edit. If there is a studentId, the edit form will be rendered else the create form.

You can see the entire Students Component here:

Part 2.

Now that the forms are set up, the next goal is to pre-fill the edit form with the selected students data. First action item: return the selected student from the array of students in the store state. The JavaScript find() function is great for this particular job as it differs from filter by returning only one object instead of an array of matches.

EditStudentForm component will gain access to the store state through props by using mapStateToProps.

const mapStateToProps = state => {return { students: state.students }}

Then create a method called findStudent . First find the student, and set the state to the students data which will in turn show up in the edit form because the value of the fields is returns the state.

findStudent = () => {const { students, studentId} = this.propsconst student = students.find(student => student.id === studentId)this.setState({id: student.id,name: student.name,school: student.school,city: student.city,state: student.state})}

Due to the Edit form being rendered only after the edit button has been selected and to avoid a maximum depth error with setState, componentDidMount is the best place to invoke the findStudent() method. This will ensure state is only set once and avoid any infinite looping.

componentDidMount(){this.findStudent()}

When the user has submitted the updates, the onSubmit event will invoke a method called update . This method will use an action creator that both makes an async call to our rails backend and dispatches an action to the reducer. (Don’t forget to configure your middleware for async redux)

Action Creator: 1. Dispatch an action to the store to render an updated student object to the user 2. Make a fetch request to persist the update to the Rails API.

export const editStudent = student => {return dispatch => {dispatch({type: 'EDIT_STUDENT', payload: student})fetch(`http://127.0.0.1:3000/students/${student.id}`, {method: 'PATCH',body: JSON.stringify(student),headers: { 'Content-Type': 'application/json'}})}}

The update method will call this action like so, passing it the state object which reflects the updated student object:

update = e => {e.preventDefault()this.props.editStudent(this.state)this.props.resetStudentId()}

resetStudentId is will set the studentId property back to false after the edit has been completed in order to render a regular form.

resetStudentId = () => {this.setState({ studentId: false})}

The complete EditStudentForm component:

I hope you find this helpful. Please let me know if you have any questions.

--

--