简体   繁体   中英

How to call class component from the functional component

Here I want to show a modal window (which is class component) when a request fails in axios interceptor response. Can anyone help me how to call Modals class instead of alerts in the below code.

     //axios interceptor 
    import React, { Component}  from 'react';
    import axios from 'axios';
    import Modals  from '../components/modalAlerts/modalalerts';
    import ReactDOM from 'react-dom';
    import ShallowRenderer from 'react-test-renderer/shallow'
    import { Button, Card, CardBody, CardHeader, Col, Modal, ModalBody, ModalFooter, ModalHeader, Row } from 'reactstrap';
    const instance = axios.create({
        baseURL: '//some url here',
        timeout: 15000,
    });
    instance.defaults.headers.common['Authorization'] = //token;
    instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
    instance.interceptors.request.use(function (config) {
        return config;
      }, function (error) {
        alert(error)
        console.log(error.response)
        return Promise.reject(error);
      });
    instance.interceptors.response.use(function (config) {
        return config;
      }, function (error) {
        console.log(error)
        if(error.response){
            if(error.response.status === 401||error.response.status === 403 ){
                console.log("401")
                localStorage.clear()
                window.location = '/#/login';
                alert(error.response.data.message)
            }else if(error.response.status === 404){
               alert(404);
            }else if(error.response.status === 400){
               alert(error.response.data.message)
            }else{
                alert("something went wrong. Please try after sometime..!")
            }
        }else{
            alert("server not found")
        }

        return Promise.reject(error);
      });
    export default instance;

here my model class component I want to call this modal from above axios interceptor instead of alerts.

     class Modals extends Component {
        constructor(props) {
            super(props);
            console.log(props)
            this.state = {
                modal: true,
            }    
            this.toggle = this.toggle.bind(this);
        }

        toggle() {
            this.setState({
                modal: !this.state.modal,
            });
        }
        render() {
            return (
                <div className="animated fadeIn">
                    <Row>
                        <Col>
                            <Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
                                <ModalHeader toggle={this.toggle}>{this.props.apistatus == 1? "Success" : "Error"}</ModalHeader>
                                <ModalBody>
                                    {this.props.apistatus == 1? "Form updated successfully" : this.props.errormsg}
                                </ModalBody>
                                <ModalFooter>
                                    <Button color="primary" onClick={this.toggle}>OK</Button>{' '}
                                    {/* <Button color="secondary" onClick={this.toggle}>Cancel</Button> */}
                                </ModalFooter>
                            </Modal>       
                        </Col>
                    </Row>
                </div>
            );
        }
    }
    export default Modals;

This problem is similar to this one . There is Axios instance that is unrelated to React application, so it cannot get modal instance to interact with it. Binding it to React component instances would be a mistake that may result in other problems, eg in tests. A proper approach is to associate Axios instance with specific application instance and provide Axios instance for entire application.

Common ways to do this are deeply passed props, context API and global state management (Redux, MobX).

Eg Axios factory function receives modal component instance to refer it:

function axiosFactory(modalRef) {
      const instance = ...;
      instance.interceptors.request.use(..., function (error) {
        const modalInstance = modalRef.current;
        modalInstance.toggle();
      });
      ...
    }

const AxiosContext = React.createContext();

class App extends Component {
  modalRef = React.createRef();

  render() {
    return <>
      <Modal ref={this.modalRef}/>
      <AxiosContext.Provider value={axiosFactory(this.modalRef)}>
        ...the rest of the app that depends on Axios...
      </AxiosContext.Provider>
    </>;
  }
}

Axios instance can be retrieved in child components:

 <AxiosContext.Consumer>{axios => (
   <ComponentThatNeedsToGetAxiosAsProp axios={axios} />
 )</AxiosContext.Consumer>

Reusability may be improved with idiomatic React recipes, eg withAxios higher-order component that makes use of <AxiosContext.Consumer> as shown above.

In case of Redux this may be even simpler because Axios instance can become available in Redux store and be decoupled from React component hierarchy. It doesn't need to get modal component directly because it can interact with it via actions.

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