首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >redux异步mapStateToProps

redux异步mapStateToProps
EN

Stack Overflow用户
提问于 2017-12-13 19:04:45
回答 1查看 7.5K关注 0票数 4

为什么在componentDidMount中调用componentDidMount函数时,mapStateToProps totalDoctorCount: state.doctors.totalDoctorCount不会总是按时加载,我会在console.log("this.props.totalDoctorCount: "+this.props.totalDoctorCount );中获得undefined结果。

我知道这是async的本质,但是有什么方法可以解决这个问题吗?我在这里做错了什么。

完整法典:

doctorActions

代码语言:javascript
复制
export function getDoctors(filterType){
return function(dispatch){
    axios.get("/api/doctors/"+filterType)
        .then(function(response){
            dispatch({type:"GET_DOCTORS",payload:response.data});
        })
        .catch(function(err){
            dispatch({type:"GET_DOCTORS_REJECTED",payload:err});
        })
}
}

export function getTotalDoctors(){
return function(dispatch){
    axios.get("/api/getTotalDoctors/")
        .then(function(response){
            dispatch({type:"TOTAL_DOCTORS",payload:response.data});
            console.log(response.data);
        })
        .catch(function(err){
            //console.log(err);
            dispatch({type:"TOTAL_DOCTORS_REJECTED",payload:"there was an error rortal doctors"});
        })
}
}

doctorReducer

代码语言:javascript
复制
export function doctorsReducers(state={
doctors:[],
}, action){
switch(action.type){
    case "GET_DOCTORS":
    // return the state and copy of boos array from state
        return {...state,doctors:[...action.payload]}
    break;

    case "TOTAL_DOCTORS":
    // return the state and copy of boos array from state
        return {
            ...state,
            totalDoctorCount:action.payload
        }
    break;

}
return state;
}

服务器API

代码语言:javascript
复制
app.get('/doctors/:filterType',function(req,res){
let filterType = req.params.filterType;
var query = {};
if(filterType == "dateCreated"){
    query = {date_created: 'desc'};
}else if(filterType == "dateUpdated"){
    query = {date_updated: 'desc'};
}
Doctors.find({}).sort(query).limit(3).exec(function(err,doctors){
    if(err){
        throw err;
    }
    res.json(doctors);
});
});

app.get('/getTotalDoctors',function(req,res){
Doctors.count({}, function(err, count){
    if(err){
        throw err;
    }
    res.json(count);
});
});

组件

代码语言:javascript
复制
class MainAdmin extends React.Component{

    constructor(){
        super();
        this.state = {
            selected_filter:"dateCreated"
        };
    }

    openAddDoctorModal = () => {
        this.setState({AddDoctorModal:true});
    }

    closeAddDoctorModal = () => {
        this.setState({AddDoctorModal:false});
    }


    componentDidMount(){
        this.props.getTotalDoctors();
        this.props.getDoctors(this.state.selected_filter);
    }



    loadPage = (pageNum) => {
        //alert(pageNum);
        this.props.loadPage(pageNum,this.state.selected_filter);
    }


    render(){

        const doctorsList = this.props.doctors.map(function(doctorsArr){
            return(
                <Col xs={12} sm={12} md={12} key={doctorsArr._id}>
                    <DoctorsItem
                        _id = {doctorsArr._id}
                        doc_fname = {doctorsArr.doc_fname}
                        doc_lname = {doctorsArr.doc_lname}
                    />
                </Col>
            )
        });

        //const lengthPage = parseInt(this.props.totalDoctorCount/3);
        console.log("this.props.totalDoctorCount2: "+this.props.totalDoctorCount );
        const pages = parseInt(this.props.totalDoctorCount/3, 10);
        console.log("pages: "+pages );

        const pageNums = [...Array(pages)].map((pageNum, i) => {
            return(
                <Col xs={2} sm={2} md={2} key={i+1}>
                    <Button onClick={() => this.loadPage(i+1)} bsStyle="success" bsSize="small">
                        {i+1}
                    </Button>
                </Col>
            )
        });

        return(
            <Well>
                <Row style={{marginTop:'15px'}}>
                    {doctorsList}
                </Row>
                <Row style={{marginTop:'15px'}}>
                    {pageNums}
                </Row>
            </Well>
        )



    }
}

function mapStateToProps(state){
    return{
        doctors: state.doctors.doctors,
        totalDoctorCount:state.doctors.totalDoctorCount
    }
}


function mapDispatchToProps(dispatch){
    return bindActionCreators({
        getDoctors:getDoctors,
        loadPage:loadPage,
        getTotalDoctors:getTotalDoctors
    },dispatch)
}
export default connect(mapStateToProps,mapDispatchToProps)(MainAdmin);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-12-13 20:06:30

有几种方法可以处理这个问题,但是您必须首先了解如何处理影响您的dom的异步操作。

每当组件挂载时(取决于您如何设置应用程序,每当对支持、状态等进行更改时),都会调用它的呈现函数。在您的示例中,组件挂载,然后向服务器请求医生列表,调用render(),然后从服务器接收医生列表。要重新定义,当它调用render方法时,它还没有收到来自axios调用的医生列表。

如果你理解了这一切我很抱歉。现在,关于this.props.totalDoctorCount返回undefined的原因:在函数getTotalDoctors解析之前,不会定义应用程序的state.totalDoctorCount (即,从服务器返回消息)。您可以通过在您的totalDoctorCount中将0定义为0(其中您将医生定义为一个空数组)来解决这个问题。

另一方面,您真的想让用户看到/认为在服务器及时响应之前总共有0医生吗?这可能是一个考虑加载组件的好机会。我喜欢做的是在render()下面,检查是否存在需要迭代的列表,如果它是空的,您可以返回一个LoadingComponent (您可以自己制作它,并在需要加载的地方使用它)。

这本身是不够的,因为您不希望页面在没有医生的情况下无限期地加载,因此只有在检索它所关注的列表的函数仍在“获取”时,此LoadingComponent才会出现。因此,您也许可以实现三个操作,它们分别是在获取之前调用、在响应fetch之后调用的,以及如果有错误的话。

因此,概述:

1) MainAdmin坐骑。

2) GetDoctorsGetTotalDoctors

3)调用了一个新的动作isFetching,将您的状态保留为:

代码语言:javascript
复制
{
    doctors: [],
    totalDoctors: 0, //assuming you have added this to defaultState
    isFetchingDoctors: true
}

4) MainAdmin调用render()

5)由于state.doctors是空的,state.isFetchingDoctorstrueMainAdmin.render()返回新的LoadingComponent

6)您的服务器使用医生列表和totalDoctorCount响应您的axios调用(注意:这将在不同的时间发生,但为了简单起见,我将它们视为一起发生)。

7)成功处理程序使用新的医生列表更新您的状态:

代码语言:javascript
复制
{
    doctors: [1, 2, 3],
    totalDoctors: 3,
    isFetchingDoctors: true
}

8)由于状态的变化,MainAdmin calls render()再次出现,但由于state.isFetchingDoctors仍然为真,它仍将显示LoadingComponent。

8)您的第二个新动作isFetched()被调用,您的状态为:

代码语言:javascript
复制
{
    doctors: [1, 2, 3],
    totalDoctors: 3,
    isFetchingDoctors: false
}

9) MainAdmin再次调用render(),但这一次表示它不再加载的条件已经满足,您可以安全地遍历医生列表。

最后一个注意事项:您也可以在还原器中将isFetching设置为false,但我个人喜欢将异步状态函数分离为它们自己的函数,以保持每个函数的座右铭,只执行一件事情。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47800412

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档