(React / Redux)组件状态未使用reducer和mapStateToProps进行更新

时间:2018-02-15 14:26:32

标签: reactjs react-redux react-thunk

我的组件状态没有使用Reducer进行更新,在mapStateToProps中得到的Reducer State很好并且出现在props中但是它不应该更新我的Component的状态以便重新渲染吗?在Reducer中返回状态 来自文档和注释的Spread语法的{...state, rows:news_formated.slice(0,30)}都说这是用于返回状态的新实例而不是改变状态本身的方法之一。下面是Action,Reducer和部分代码的代码。

class CreateGenericTable extends Component {    

    constructor(props){
        super(props);
        this.state = {  rows:null, columns:null};
    } 

    componentDidMount(){

        var token = getCookie('admin_session_token');
        servicerequest = this.props.serviceRequest;

        this.setState({columns: this.props.columns})

        var teste = this.props.tableList(this.props.editform,this.props.service,token,servicerequest,this.props.columns)
        console.log(this.props);
    }
}  

function mapDispatchToProps(dispatch){
    return bindActionCreators({ tableList, editComponent }, dispatch);
}

const mapStateToProps = (state,ownProps) => { 
    console.log('this is state');
    //console.log(state);

    if(state.tabledata.rows!=null){
        debugger;
        return { rows: state.tabledata.rows};
    }else{
        return { rows: null};
    }

};

//export default connect(null, mapDispatchToProps)(CreateGenericTable)
const CreateGenericTableRedux = connect(mapStateToProps, mapDispatchToProps)(CreateGenericTable)

动作

import $ from "jquery";//https://redux.js.org/docs/advanced/AsyncActions.html Asynchronous calls need to use thunk of redux.....

//import { connect } from 'react-redux';

export const FETCH_TABLEDATA = 'FETCH_TABLEDATA'
export const EDIT_COMP = 'EDIT_COMP'

export function editComponent(id,View){
    return {
        type: EDIT_COMP,
        payload: {'id':id,'View':View}
    }
}

export function tableList(editform,service,token,serviceRequest){

    var request = null;

    return dispatch => {
        $.ajax({
            type: "POST",
            url: service,
            crossDomain: true,
            dataType: 'jsonp',
            xhrFields: {
                withCredentials: true
            },
            data: { 
                q: JSON.stringify({
                    [serviceRequest]:{}
                }),
                admin_session_token:token, 
            },
            success : (data) => {   
                request = data;
                dispatch({
                    type: FETCH_TABLEDATA,
                    payload: {editform: editform,request: request, serviceRequest: serviceRequest }
                });            
            },

            error: (xhr, status, err) =>{
                ////console.log('ups somehting went rong:'.err.toString());
            },

        }); 
    };          

    /*
    return request.then ({
        type: FETCH_TABLEDATA,
        payload: {request: request, serviceRequest: serviceRequest, columns: columns}
    });
    */

}

减速

import { FETCH_TABLEDATA } from '../actions/index.js'

//const INITIAL_STATE = {rows:null, columns:[]} //separate the data proprocessing to a function -> https://gist.github.com/abhiaiyer91/aaf6e325cf7fc5fd5ebc70192a1fa170

export default function(state = [], action){    switch(action.type){        case FETCH_TABLEDATA:
            var data = action.payload.request[action.payload.serviceRequest];//var data = data['News_get'];
            console.log('----state---');            console.log(state);

            if(data.length>0){
                var news_formated = [];
                var listofkeys = Object.keys(data[0]);

                for(var new_unformated of data){
                    var new_formated = [];
                    //console.log(new_unformated);
                    for(var key of listofkeys){

                        //console.log(key);
                        if(action.payload.editform.indexOf('EditHeader') !== -1 && key.indexOf('language_items') !== -1){
                            new_formated['image'] = new_unformated[key][0]['image'];
                            new_formated['link'] = new_unformated[key][0]['link'];
                        }else{

                            if(action.payload.editform.indexOf('EditNotification') !== -1){
                                if(key.indexOf('params') !== -1){
                                    new_formated[key] = new_unformated[key]['message'];
                                }else{
                                    new_formated[key] = new_unformated[key];
                                }
                            }else{
                                if(key.indexOf('active') !== -1){
                                    if(new_unformated[key].indexOf('1') !== -1){
                                        new_formated[key] = 'Yes';
                                    }else{
                                        new_formated[key] = 'No';
                                    }
                                }else{
                                    new_formated[key] = new_unformated[key];
                                }
                            }

                        }


                    }

                    news_formated.push(new_formated);

                }

                return {
                            ...state,
                            rows:news_formated.slice(0,30)
                        };
            }else{
                return {
                            ...state,
                            rows:null
                    };
            }
            //{...state, {rows:null, columns:action.payload.columns}};      default:            return {
                            ...state,
                            rows:null
                    };  } }

1 个答案:

答案 0 :(得分:2)

componentDidMount函数仅在第一次渲染时被调用,然后组件才会安装,因此在redux存储中的任何进一步更新,反映在组件的道具中都不会在您的实现中设置为状态。您需要在componentWillReceiveProps函数

中实现相同的逻辑

另外为了提醒你它的反模式有一个可以直接从道具派生的状态,你应该直接使用道具。

虽然你可以实现你想要的目标

class CreateGenericTable extends Component {    

    constructor(props){
        super(props);
        this.state = {  rows:null, columns:null};
    } 

    componentDidMount(){

        var token = getCookie('admin_session_token');
        servicerequest = this.props.serviceRequest;

        this.setState({columns: this.props.columns})

        var teste = this.props.tableList(this.props.editform,this.props.service,token,servicerequest,this.props.columns)
        console.log(this.props);
    }
    componentWillReceiveProps(nextProps) {
         if(nextProps.columns !== this.props.columns) { // You might need to have a deep comparison here if columns is not immutable or a nested obejct. You can use _.isEqual from lodash in that case
             this.setState({columns: nextProps.columns})
         }
    }
}  

function mapDispatchToProps(dispatch){
    return bindActionCreators({ tableList, editComponent }, dispatch);
}

const mapStateToProps = (state,ownProps) => { 
    console.log('this is state');
    //console.log(state);

    if(state.tabledata.rows!=null){
        debugger;
        return { rows: state.tabledata.rows};
    }else{
        return { rows: null};
    }

};

export default connect(null, mapDispatchToProps)(CreateGenericTable)

如果可能,我会严格建议您直接在组件中使用this.props.columns,而不是将其保持在状态