Как структурировать приложение React для передачи значений, возвращаемых дочерней функцией - PullRequest
0 голосов
/ 26 июня 2019

Я создаю приложение реагирования, которое я хочу разделить на три уровня, и у меня возникли небольшие проблемы, когда я обдумываю, как их следует структурировать и в какой иерархии лучше всего поддерживать методы React.

Три уровня: сервис (только вызовы API), бизнес-логика и пользовательский интерфейс. Моя цель здесь - обеспечить возможность многократного использования сервисного и бизнес-уровней и не привязывать их к конкретным компонентам пользовательского интерфейса.

Так что, на мой взгляд, структура моей программы должна быть UI> (является родителем) Business logic> (является родителем) уровня обслуживания. Однако мне трудно понять, как этот подход имеет смысл в реакции, поэтому мне интересно, правильная ли это идея. Моя проблема в том, что, как я понимаю, родители передают реквизит детям. Однако мне нужен сервисный уровень для передачи объектов в мою бизнес-логику, чтобы он мог выполнять свои функции и эффективно передавать его в пользовательский интерфейс для отображения.

Вот урезанная версия моего сервисного слоя:

interface State {
    queues: any
}

@observer
class DeadletterService extends Component<Props, State> {

    @observable deadletterQueue: [];
    @observable queues: [];

    constructor(props: any) {
        super(props);
        this.state = {
            queues: []
        };

        this.queues = this.getQueues();
        this.deadletterQueue = this.getByQueue("urlSlug");
    }

    // returns all queues as a JSON array
    getQueues(): any {

        let url = "url";

        fetch(url)
            .then(res => res.json())
            .then(data => {
                return data;
            });
    }

    // given the name of a queue, returns the queue's deadletters as a JSON array
    getByQueue(id: string): any {

        let url = "url/{id}";

        fetch(url)
            .then(res => res.json())
            .then(data => {
                return data;
            });

        return 
    }

    render() {
        return (
            <div>
                <DeadletterLogic testQueues={this.queues}  /> 
            </div>
        );
    }
}

А вот урезанная версия моего логического слоя:

interface Props {
    testQueues: any;
}

interface State {
    queues: any
}

@observer
class DeadletterLogic extends Component<Props, State> {

    constructor(props: any) {
        super(props);
        this.state = {
            queues: []
        };
        this.getQueues();
    }

    // here is where the business logic will be done
    getQueues() {
        // in order to gets a list of queues here, a fetch call must be made in the service layer to the MessageQueueAPI
    }

    componentDidMount() {
        // when passing from a parent, I'm not sure if this needs to live here or if it can live in getQueues to update when the fetch is finished.
        this.setState({ queues: this.props.testQueues });
    }

    render() {
        return (
            <div>
                {this.props.testQueues}
            </div>
        );
    }
}

Каков наилучший способ получить значения, возвращаемые вызовом API в моем слое обслуживания, в бизнес-уровень в React? Поскольку это асинхронный вызов извлечения, мне также нужно обновить свой бизнес-уровень после того, как я действительно получу данные обратно.

Ура!

1 Ответ

1 голос
/ 27 июня 2019

Я не уверен, почему вы используете свой сервис и бизнес-уровень в качестве компонентов? Как вы сказали

Моя цель здесь - позволить сервису и бизнесу быть может использоваться повторно и не привязываться к конкретным компонентам пользовательского интерфейса.

Это означает, что они не должны быть связаны с каким-либо пользовательским интерфейсом. Это означает, что эти уровни можно использовать в угловой, реактивной или любой другой реализации уровня пользовательского интерфейса.

Таким образом, вы можете иметь API-слой (сервис):

class DeadletterService {
    async getQueues(filter) {
        const response = await fetch(...);
        return await response.json();
    }

    // other api calls
}

const service = new DeadletterService();
export default service;

Как вы можете видеть, сервис просто запрашивает и возвращает данные (без состояния) на основе некоторого ввода (например, фильтра, идентификатора или чего-то еще).

Затем у вас есть бизнес-уровень, на котором вы выбираете данные из сервисов, выполняете любые преобразования данных, которые вы хотите, и сохраняете эти данные в каком-то состоянии, которое будет использоваться на уровне пользовательского интерфейса.

import deadLetterService from './deadLetterService';

class DeadletterStore {
    @observable queues = [];

    @action
    async getQueues() {
        const queues = await deadLetterService.getQueues();
        // do some mapping if needed
        this.queues = queues;
    }
}

Теперь вы можете использовать это хранилище внутри вашего пользовательского интерфейса - поскольку вы используете MobX, вы можете использовать функцию инъекции:

@inject('deadLetterStore');
class DeadletterPage extends React.Component {
    componentDidMount() {
        this.props.deadLetterStore.getQueues();
    }

    render() {
        return (
            <div>
                {this.props.deadLetterStore.queues.map((queue) => <span>{queue.name}</span>)}
            </div>
        )
    }
}

Пожалуйста, обратите внимание, что этот код не тестировался - он просто указывает на структуру конструкции.

...