I am calling a redux action which makes a get request to the database and returns an object with the correct data in it. I have followed the object through the system showing it is being sent correctly all the way to the react component, however, when the redux action is called, the object does not get updated. If a second call is made then the state is updated. I assume this has something to do with asynchronous behavior but I am unsure how to fix it.
Here are the relevant parts of the component calling the action:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { MDBContainer, MDBInput, MDBBtn } from 'mdbreact';
import { getSinglePatient } from '../../../actions/patientActions';
import PatientConfirmModal from '../../modals/PatientConfirmModal';
export class SelectPatient extends Component {
state = {
patientConfirmModalToggle: false,
patient: {},
searchID: ''
};
static propTypes = {
patient: PropTypes.object.isRequired,
getSinglePatient: PropTypes.func.isRequired
};
onChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
toggleConfirmModal = () => {
this.setState({
patientConfirmModalToggle: !this.state.patientConfirmModalToggle
});
};
searchForPatient = () => {
this.props.dispatch(getSinglePatient(this.state.searchID)); // edit 1
console.log(this.props.patient);
const newPatient = this.props.patient.patients[0];
console.log(newPatient);
if (newPatient !== undefined) {
this.setState({
patient: newPatient
});
this.toggleConfirmModal();
}
console.log(this.state.patient);
};
render() {
return (
<MDBContainer>
<h3>Please enter a Patient ID to begin an assessment</h3>
<MDBInput
label="Patient ID"
group
type="text"
name="searchID"
id="searchID"
onChange={this.onChange}
/>
<MDBBtn
onClick={() => this.searchForPatient()}
>
Search
</MDBBtn>
<PatientConfirmModal
modal={this.state.patientConfirmModalToggle}
patient={this.state.patient}
toggle={this.toggleConfirmModal}
/>
</MDBContainer>
);
}
}
function mapStateToProps(state){
console.log(state)
return{
patient: state.patient
}
}
export default connect(mapStateToProps , {getSinglePatient})(SelectPatient);
Here is the action itself:
export const getSinglePatient = id => (dispatch, getState) => {
dispatch(setPatientsLoading());
axios
.get(`/api/patients/${id}`, tokenConfig(getState))
.then(res =>
dispatch({
type: GET_SINGLE_PATIENT,
payload: res.data[0]
})
)
.catch(err =>
dispatch(returnErrors(err.response.data, err.response.status))
);
};
And here is the route it is being sent to:
// @route GET api/patients
// @desc Get a single patient
// @access Public
router.get('/:id', (req, res) => {
console.log('GET single request hit (ID:' + req.params.id + ')');
Patient.find({ patientID: req.params.id }).then(patient => {
res.json(patient);
});
});
Here are the results of the console log (first result on pressing search button once, second on pressing again and calling the action a second time):
Edit: Updated error from code suggested below (patient has been switched to the client but this has no impact on the code as it has been entirely refactored)
Results: