Использование одного объекта Axios для всего приложения с использованием контекста

#reactjs #express #axios #react-context

#reactjs #выразить #axios #реагировать-контекст

Вопрос:

У меня есть приложение с несколькими уровнями дочерних элементов. В этом примере я объявил Context.js и a ContextDBConnector.js , они используются таким образом:

Context.js

 import React from 'react';

export const ContextDB = React.createContext();
  

ContextDBConnector.js

 import React, {Component} from 'react'
import {ContextDB} from './Context'

class ContextDBConnector extends Component {

    render(){

        return (
            <ContextDB.Provider value = {{
                
                callAPI() {

                    const axios = require('axios').default
                    
                    axios.get('http://localhost:5000/person_by_first_name', {
                        params: {
                            firstname: "Marcus"
                        }
                    })
                    .then(function (response) {
                        console.log("Printing out response")
                        console.log(response);
                    })
                    .catch(function (error) {
                        console.log(error);
                    })
                    .then(function () {
                        // always executed
                    })
                }
            }}>

            {this.props.children}

            </ContextDB.Provider>
        )
    }
}

export default ContextDBConnector;
  

index.js

 import React from 'react';
import ReactDOM from 'react-dom';
import * as serviceWorker from './serviceWorker';
import App from './components/App.js';
import {navData} from './js/const';
import {footerData} from './js/const';
import ContextDBConnector from './context/ContextDBConnector'

ReactDOM.render(
  <React.StrictMode>
    <ContextDBConnector>
      <App key = "0" navData =  {navData} footData = {footerData} />
    </ContextDBConnector>
  </React.StrictMode>,
  document.getElementById('root')
);


serviceWorker.unregister();
  

Пока все идет хорошо. Теперь я могу использовать контекст для вызова context.callAPI() изнутри компонента, расположенного далеко по линии дочерних элементов, таким образом:

Image.js

 import React, {Component} from 'react'
import {ContextDB} from '../context/Context'

class Image extends Component {
    
    static contextType = ContextDB

    componentDidMount(){

        this.context.callAPI()

    }

    render(){
        
        const obj = this.props.obj

        return (
            <div className={obj.classCont}>
                <img className={obj.class} src={obj.url} alt='' />
            </div>
        );
    }
}

export default Image;
  

This works well and looking at the javascript console in Chrome, ContextDBConnector.js is printing out what it should:

Распечатка ответа

ContextDBConnector.js:23 {данные: массив (1), статус: 200, statusText: «OK», заголовки: {…}, конфигурация: {…}, …}

Теперь мне трудно получить объект ответа из component ContextDbConnector в component Image, чтобы он мог использовать необходимые ему данные. Я попробовал что-то подобное, и это, очевидно, не сработало:

Image.js

 import React, {Component} from 'react'
import {ContextDB} from '../context/Context'

class Image extends Component {
    
    static contextType = ContextDB

    componentDidMount(){

        this.context.callAPI().then(response => {
            console.log("Person has been returned")
        });

    }

    render(){
        
        const obj = this.props.obj

        return (
            <div className={obj.classCont}>
                <img className={obj.class} src={obj.url} alt='' />
            </div>
        );
    }
}

export default Image;
  

Не могли бы вы помочь мне разобраться в той части, где Image получает необходимые данные из ContextDBConnector?

Полное раскрытие: я только начал изучать React, Express, Mysql, Axios и Node.js как и месяц назад, поэтому я заранее приношу извинения, если я неправильно понимаю некоторые концепции здесь, и моя логика кода не очень сильна: D Это моя первая попытка с контекстом, и я немного застрял с этой частью.

Просто чтобы было понятно, чего я пытаюсь достичь здесь, это иметь только один объект axios для всего приложения, чтобы разные части могли получить к нему доступ и добраться до разных маршрутизаторов на экспресс-сервере (серверной части) вместо создания экземпляров axios повсюду.

Если способ, которым я пытаюсь добиться этого, не очень хорош, не могли бы вы показать мне лучший способ? В противном случае, не могли бы вы помочь мне получить данные из ContextDBConnector в Image таким образом, чтобы изображение ожидало получения фактического объекта, прежде чем делать что-либо еще?

Спасибо и высоко ценится!

Комментарии:

1. Почему ваш Image компонент должен вызывать API? Это компонент изображения, все, что он должен делать, это просто показывать изображение, верно? Ваша архитектура приложения выглядит немного неправильной для меня. Не могли бы вы подробно рассказать мне, как это должно работать, чтобы я мог дать ваше предложение о том, как правильно его спроектировать?

2. Привет, Пратик, в данном случае я использую Image, потому что это единственный компонент, который я реализовал на самом глубоком уровне, поэтому вы можете игнорировать тот факт, что это компонент изображения, это может быть компонент текстового столбца или текстовый двойной столбец и т.д. По структуре это полностью стандартно: дерево, начинающееся с индекса, затем приложение, а затем ряд компонентов, каждый со своими подкомпонентами и так далее. Контекст и context-provider находятся на том же уровне, что и index.

3. Сегодня я нашел другой способ выполнения того, что я пытаюсь сделать без контекста: codementor.io/@capocaccia / … , это решило бы мою проблему с возвратом объекта, если это сработает, поэтому я попробую это позже и посмотрю, является ли это более чистым решением.

Ответ №1:

кажется, вам следовало изменить callAPI , потому что он не возвращает объект Promise, чтобы вы могли использовать .then() и .catch()