简体   繁体   中英

AJAX finish after my render() component - ReactJS - React-Router - JQuery -

I have next ReactJS component (It only render routes):

export default class Routes extends React.Component {
    constructor() {
        super();

        this.state = {
            isAdmin: true,
            isAlumno: true,
            isProf: true
        }
    }

    componentWillMount() {
        this.cambiarEstado();
    }

    cambiarEstado() {
        //HERE IS THE PROBLEM
        $.ajax({
            url: "http://namey.muffinlabs.com/name.json?",
            data: "&with_surname=true&count=3&type=%22%22",
            type:"GET",
            dataType: "JSON",
        })
        .done((respuesta) => {
            //console.log(respuesta);
            this.setState({
                isAdmin: false,
                isAlumno: false,
                isProf: false
            })

        }).fail(function(respuesta){
            //console.log("¡Algo fué mal!");
        })
    }

    render() {
        return (
            <Router history={browserHistory}>

                <Route path="/" component={NotFound}/>
                <Redirect from="/alumno" to="/alumno/inicio"/>
                <Redirect from="/administrador" to="/administrador/inicio"/>

                <Route path="/" component={App}>

                    <Route path="alumno" component={AppAlumno}>
                        <Route path="inicio" component={RequireAlumno(Alumno_Inicio, this.state)}/>
                        <Route path="nueva_incidencia" component={RequireAlumno(Alumno_NuevaIncidencia, this.state)}/>
                        <Route path="mis_incidencias" component={RequireAlumno(Alumno_MisIncidencias, this.state)}/>
                    </Route>

                    <Route path="administrador" component={AppAdministrador}>
                        <Route path="inicio" component={RequireAdministrador(Administrador_Inicio, this.state)}/>
                        <Route path="nueva_incidencia" component={RequireAdministrador(Administrador_NuevaIncidencia, this.state)}/>
                        <Route path="incidencias_recibidas" component={RequireAdministrador(Administrador_IncidenciasRecibidas, this.state)}/>
                        <Route path="incidencias_recibidas/nuevo_informe" component={RequireAdministrador(Administrador_NuevoInforme, this.state)}/>
                        <Route path="informes" component={RequireAdministrador(Administrador_Informes, this.state)}/>
                        <Route path="informes/nueva_respuesta_informe/:id" component={RequireAdministrador(Administrador_NuevaRespuestaInforme, this.state)}/>
                    </Route>

                    <Route path="/profesor/informes/nueva_respuesta_informe/:id" component={RequireProfesor(Profesor_NuevaRespuestaInforme, this.state)}/>

                </Route>

                <Route path="/:loggedAs/acceso_restringido" component={AccesoNoPermitido}/>
                <Route path='/404' component={NotFound} />

                <Redirect from='*' to='/404' />

            </Router>
        );
    }
}

But when I want do an AJAX, which changes the state of my component (this.cambiarEstado()), I receive next error: Error: Warning: [react-router] You cannot change ; it will be ignored.

The error is due to AJAX. Once loaded method render AJAX continue executing and when it finish try to change State. But it is not valid due to I pass state into method Render() in functions as (isAdministrador(), isAlumno(),...) so the state passed is the initial state, the new state received from AJAX does not exist, and I get that error. How could I solve this? (AJAX query finish earlier than method render, which allow me to pass correct states received from AJAX)

Thank you.

You can change the state after render has run. I think your real problem is the use of this in cambiarEstado . Try putting the following line in your constructor:

this.cambiarEstado = this.cambiarEstado.bind(this);

But, I just noticed another problem. You are trying to define routes. You are not allowed to change routes once they have been defined. You can handle that by creating a Loading component and having your render method return that component instead of the routes until the ajax function has completed. After which, you can then have your render method return the routes. Something like this (some code deleted to simplify):

export default class Routes extends React.Component {
    constructor() {
        super();

        this.state = {
            dataLoaded: false,
            isAdmin: true
        }

        this.cambiarEstado = this.cambiarEstado.bind(this);
    }

    componentWillMount() {
        this.cambiarEstado();
    }

    cambiarEstado() {
        $.ajax({
            url: "http://namey.muffinlabs.com/name.json?",
            data: "&with_surname=true&count=3&type=%22%22",
            type:"GET",
            dataType: "JSON",
        })
        .done((respuesta) => {
            this.setState({
                dataLoaded: true,
                isAdmin: false
            })
    }

    render() {

        if ( ! this.state.dataLoaded) {
          return (<div>Loading....</div>);
        }

        return (
            <Router history={browserHistory}>

                <Route path="/" component={NotFound}/>
                <Redirect from="/alumno" to="/alumno/inicio"/>
                <Redirect from="/administrador" to="/administrador/inicio"/>

                <Route path="/" component={App}>

                    <Route path="alumno" component={AppAlumno}>
                        <Route path="inicio" component={RequireAlumno(Alumno_Inicio, this.state)}/>
                    </Route>

                    <Route path="administrador" component={AppAdministrador}>
                        <Route path="inicio" component={RequireAdministrador(Administrador_Inicio, this.state)}/>
                    </Route>

                    <Route path="/profesor/informes/nueva_respuesta_informe/:id" component={RequireProfesor(Profesor_NuevaRespuestaInforme, this.state)}/>

                </Route>

            </Router>
        );
    }
}

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