简体   繁体   中英

Redux action needing to be called twice before updating state?

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:结果


  
  
    //make sure you are dispatching your action like below
   // this.props.dispatch(your_action())
     
     searchForPatient = () => {
        this.props.dispatch(getSinglePatient(this.state.searchID)); //make change
        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);
    }
   
     
    //use mapStateToProps function  to access your resultent data comes from server : you can get your result in this.props
   //put this funcion above export default co.... 
   function mapStateToProps(state){
        console.log(state)
        return{
            patient : state.patient
        }
    }


    export default  connect(mapStateToProps , {getSinglePatient} )(SelectPatient)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM