【问题标题】:react router not loading id and handling error反应路由器未加载ID并处理错误
【发布时间】:2018-09-07 09:29:28
【问题描述】:

我已尝试按照 udemy 指南来实施反应路由器。我遇到的问题是直接使用 id 加载页面而不先通过列表页面。它似乎没有加载记录。我想去页面/commsmatrix/approve/121并加载记录121。我正在使用react router v4。在mapStateToPropsrecordsundefined

approve.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchCommsmatrix } from '../../actions/commsmatrices';
import { bindActionCreators } from 'redux';
import FontAwesome from 'react-fontawesome';

class Approve extends Component {
    constructor(props) {
        super(props);
        this.meta = { title: 'Comms Matrix Approval', description: 'Sox approval' };
        this.runOnce = false;
        this.passMetaBack = this.passMetaBack.bind(this);
        this.initConfirm = this.initConfirm.bind(this);
    }

    componentDidMount() {
        this.passMetaBack;
        const { id } = this.props.match.params.id;
        this.props.fetchCommsmatrix(id);
    }

    passMetaBack = () => {
        this.props.passMetaBack(this.meta);
    };

    initConfirm(){
        this.runOnce = true;
        /*this.props.fetchCommsmatrix(121)
        .then(function(response){
            console.log(response);
            let data = response.payload.data;
            if(data.header.error){
                self.setState({ 
                    showError: true,
                    errorMsg: data.header.message
                });
            }else{

            }
        });*/

    }

    render() {
        console.log(this);
        if(!this.runOnce && this.props.isReady){
            this.initConfirm();
        }

        const { record } =  this.props ;
        console.log(record);

        let message = <div>Confirming...<i className="fa fa-spinner fa-spin"></i></div>;
        return (
            <div className="container-fluid">
                <div className="row-fluid top-buffer">{message}</div>
            </div>
        );
    }
}

function mapStateToProps({ records }, ownProps) {
    console.log(records);
console.log(ownProps);
    return { record : records[ownProps.match.params.id] };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(
        { fetchCommsmatrix },
        dispatch
    );
}

export default connect(mapStateToProps, { fetchCommsmatrix })(Approve);

这是我的操作

import axios from 'axios';

export const FETCH_COMMSMATRIX = 'fetch_commsmatrix';

export function fetchCommsmatrix(id) {
    const request = axios.get(`/api/user/comms/matrices/id/`+id+`/format/json?quiet=1`);    
    return {
        type: FETCH_COMMSMATRIX,
        payload: request
    };
}

export const FETCH_COMMSMATRICES_BY_SERVICE = 'fetch_commsmatrices_by_service';

export function fetchCommsmatricesByService(service_id) {
    const request = axios.get(`/api/user/comms/matrices/format/json?quiet=1&service_id=`+service_id);   
    return {
        type: FETCH_COMMSMATRICES_BY_SERVICE,
        payload: request
    };
}

这是我的reducer

import { FETCH_COMMSMATRIX, FETCH_COMMSMATRICES_BY_SERVICE } from '../actions/commsmatrices';

export default function(state = {}, action) {
    switch (action.type) {
    case FETCH_COMMSMATRIX:
        return { ...state, [action.payload.data.body.recordset.record[0].id] : action.payload.data.body.recordset.record[0] };
    case FETCH_COMMSMATRICES_BY_SERVICE:        
        return action.payload.data.body.recordset.record;
    default:
        return state;
    }
}

这里是索引缩减器

import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form'; 
import ActiveUserReducer from './reducer_active_user';
import CommsmatricesReducer from './reducer_commsmatrices';
import ContentReducer from './reducer_content';
import ContentVideListReducer from './reducer_content_video_list';
import SecurityExemptionsReducer from './reducer_security_exemption';
import ReportsWorkerJobs from './reducer_reports_workerjobs';
import ReportsWorkerJobsCount from './reducer_reports_workerjobs_count';
import ReportsFactsandfigures from './reducer_reports_factsandfigures';
import ReportsFactsandfiguresCount from './reducer_reports_factsandfigures_count';
import ServicesReducer from './reducer_services';
import ServicesEditCheckReducer from './reducer_services_edit_check';
import ServicesAddReducer from './reducer_services_add';
import ServicesRenameReducer from './reducer_services_rename';
import ServicesRemoveReducer from './reducer_services_remove';
import TemplatesReducer from './reducer_templates';

const rootReducer = combineReducers({
    form: formReducer,
    activeUser: ActiveUserReducer,
    commsmatrices: CommsmatricesReducer,
    content: ContentReducer,
    contentVideoList: ContentVideListReducer,
    reportsWorkerJobs: ReportsWorkerJobs,
    reportsWorkerJobsCount: ReportsWorkerJobsCount,
    securityExemptions: SecurityExemptionsReducer,
    reportsFactsAndFigures: ReportsFactsandfigures,
    reportsFactsAndFiguresCount: ReportsFactsandfiguresCount,
    services: ServicesReducer,
    servicesEditCheck: ServicesEditCheckReducer,
    servicesAdd: ServicesAddReducer,
    servicesRename: ServicesRenameReducer,
    servicesRemove: ServicesRemoveReducer,
    templatesReducer: TemplatesReducer
});

export default rootReducer;

这里是应用

import React, { Component } from 'react';
import { Switch, Route, withRouter, Redirect } from 'react-router-dom';
import ReactGA from 'react-ga';
import { connect } from 'react-redux';
import { fetchActiveUser } from './actions/index';
import { bindActionCreators } from 'redux';
import { getHttpRequestJSON } from './components/HTTP.js';

import Header from './components/header';
import Logout from './components/logout';
import SideBar from './components/sidebar';
import HomeContent from './containers/home';
import Ldapuser from './components/ldapuser';
import Admin from './components/admin/admin';
import Services from './components/services/index';
import SecurityExemptionsNew from './components/security/security_exemptions_new';
import WorkerJobs from './components/reports/workerjobs';
import FactsAndFigures from './components/reports/factsandfigures';
import Approve from './components/commsmatrix/approve';
import CommsMatrixTemplates from './components/commsmatrix/templates';
import CommsMatrixTemplate from './components/commsmatrix/template';

ReactGA.initialize('UA-101927425-1');

function fireTracking() {
    ReactGA.pageview(window.location.pathname + window.location.search);
}

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isGuest: false,
            isSupp: false,
            priv: [],
            loading: true,
            version: '',
            redirect: false,
            title: 'Home',
            description: '',
            isReady: false
        };
    }

    setRedirect = () => {
        this.setState({
            redirect: true
        });
    };

    renderRedirect = () => {
        //if (this.state.redirect) {
            return <Redirect to="/SSOLogon/manual_login.jsp" />;
        //}
    };

    initData = () => {
        let self = this;

        getHttpRequestJSON(
            '/api/user/get/user/method/is/guest/format/json?quiet=1'
        )
            .then(response => {
                let isGuest = response.body.recordset.record.isGuest;
                if (isGuest) {
                    /*$(".logo").trigger('click');
            //$("#overlay").show();
            $('#modalIntro').modal('toggle');

            $("#modalIntro").on("hidden.bs.modal", function () {
              $(".logo").trigger('click');
            });*/
                }

                //self.props.isGuest = isGuest;
                //self.props.loading = false;
                //self.props.version = response.header.version;
                self.setState({
                    loading: false,
                    version: response.header.version,
                    isGuest: isGuest
                });
            })
            .catch(error => {
                console.log('Failed!', error);
                //$('#myModalError .modal-body').html(error);
                //$('#myModalError').modal('show');
            });

        getHttpRequestJSON(
            '/api/user/get/user/method/is/supp/format/json?quiet=1'
        )
            .then(response => {
                self.setState({
                    isSupp: response.body.recordset.record.isSupp
                });
            })
            .catch(error => {
                console.log('Failed!', error);
                //$('#myModalError .modal-body').html(error);
                //$('#myModalError').modal('show');
            });

        getHttpRequestJSON(
                '/api/user/get/user/method/priv/format/json?quiet=1'
            )
                .then(response => {
                    self.setState({
                        priv: response.body.recordset.record
                    });
                })
                .catch(error => {
                    console.log('Failed!', error);
                    //$('#myModalError .modal-body').html(error);
                    //$('#myModalError').modal('show');
                });
    };

    componentDidMount() {
        let self = this;
        this.props.fetchActiveUser()
        .then(() => {
            self.initData();

        })
        .then(() => {
            self.setState({
                isReady : true
            });
        })
        if (this.props.activeUser.name == 'AuthError') {

            this.setRedirect();
        }

    }

    passMetaBack = (meta) => {
        this.setState({
            title: meta.title,
            description: meta.description
        })
    }

    render() {
        if (this.props.activeUser.name == 'AuthError') {
            //console.log('redirect');
            this.renderRedirect();            
        }
        return (
            <div>
                <Header
                    activeUser={this.props.activeUser}
                    loading={this.state.loading}
                    version={this.state.version}
                    title={this.state.title}
                    description={this.state.description}
                />
                <SideBar isReady={this.state.isReady} />
                <main>
                    <Switch>
                        <Route
                            path="/commsmatrix/approve/:id"
                            component={Approve}
                        />
                    </Switch>
                </main>
            </div>
        );
    }
}

//export default App;
function mapStateToProps(state) {
    if (state.activeUser.id > 0) {
        ReactGA.set({ userId: state.activeUser.id });
    }
    // Whatever is returned will show up as props
    // inside of the component
    return {
        activeUser: state.activeUser
    };
}

// Anything returned from this function will end up as props
// on this container
function mapDispatchToProps(dispatch) {
    // Whenever getUser is called, the result should be passed
    // to all our reducers
    return bindActionCreators({ fetchActiveUser }, dispatch);
}

//Promote component to a container - it needs to know
//about this new dispatch method, fetchActiveUser. Make it available
//as a prop
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App));

index.js

import './scripts/api';
import React, { Component } from 'react'
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { BrowserRouter, Route, browserHistory } from 'react-router-dom';
import promise from 'redux-promise';
import App from './App'
import reducers from './reducers';
import 'react-quill/dist/quill.snow.css'; // ES6

require("babel-core/register");
require("babel-polyfill");

const createStoreWithMiddleware = applyMiddleware(promise)(createStore);

ReactDOM.render(
        <Provider store={createStoreWithMiddleware(reducers)}>
            <BrowserRouter history={browserHistory}>
                <App/>
            </BrowserRouter>
        </Provider>
        , document.getElementById('root'));

更新

所以我更新了records 以匹配reducer 名称。似乎可行,但需要一种在没有记录时处理错误的方法

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchCommsmatrix } from '../../actions/commsmatrices';
import { bindActionCreators } from 'redux';
import FontAwesome from 'react-fontawesome';

class Approve extends Component {
    constructor(props) {
        super(props);
        this.meta = { title: 'Comms Matrix Approval', description: 'Sox approval' };
        this.runOnce = false;
        this.passMetaBack = this.passMetaBack.bind(this);
        this.initConfirm = this.initConfirm.bind(this);
    }

    componentDidMount() {
        this.passMetaBack;
        const id = this.props.match.params.id;
        this.props.fetchCommsmatrix(id);
    }

    passMetaBack = () => {
        this.props.passMetaBack(this.meta);
    };

    initConfirm(){
        this.runOnce = true;
    }

    render() {

        let message = <div>Confirming...<i className="fa fa-spinner fa-spin"></i></div>;

        const { commsmatrix } =  this.props ;

        if(!this.runOnce && this.props.isReady && Object.keys(commsmatrix).length > 0 ){
            this.initConfirm();
        }

        return (
            <div className="container-fluid">
                <div className="row-fluid top-buffer">{message}</div>
            </div>
        );
    }
}

function mapStateToProps({ commsmatrices }, ownProps) {

    return { commsmatrix : commsmatrices[ownProps.match.params.id] };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(
        { fetchCommsmatrix },
        dispatch
    );
}

export default connect(mapStateToProps, { fetchCommsmatrix })(Approve);

【问题讨论】:

    标签: react-router react-redux react-router-v4 reducers


    【解决方案1】:

    为了完整起见,我可以查看您的根 index.js 吗?不幸的是,我不能使用 cmets。

    你为什么有const { id } = this.props.match.params.id;

    不应该只是const { id } = this.props.match.params;

    你的状态对象甚至有记录属性吗?

    【讨论】:

    • records 来自哪里?
    • 显然records应该来自function mapStateToProps({ records }, ownProps) { console.log(records); console.log(ownProps); return { record : records[ownProps.match.params.id] }; }状态
    猜你喜欢
    • 1970-01-01
    • 2021-03-01
    • 2016-03-07
    • 2019-07-03
    • 2016-01-04
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多