Реагируйте TypeScript - Государство никогда не должно быть экспортировано? - PullRequest
1 голос
/ 30 апреля 2019

У меня есть приложение React, которое асинхронно получает info с методом getInitialInfo.MessageView является самым верхним компонентом, поэтому Данные должны жить в своем состоянии, даже если оно не изменится.В идеальном мире IMessageInfo будет проходить через реквизиты .

Нам нужно export типа IMessageInfo, потому что есть код, который зависит от этого интерфейса .


ВАРИАНТ 1 - (Плоское решение без частного состояния)

import * as React from 'react';
import Message from './Message';

// IMessageInfo needs to be exported because there is code that depends on it
export interface IMessageInfo {
    message: string;
    icon: string;
}

export interface IMessageViewProps {
    getInitialInfo(): Promise<IMessageInfo>;
}

// MessagesView is the upper most Component 
class MessageView extends React.Component<IMessageViewProps, IMessageInfo> {
    constructor(props) {
        super(props);
        this.state = {
            message: '',
            icon: ''
        };
        this.getInitialInfo();
    }

    private async getInitialInfo(): void{
        let info = await this.props.getInitialInfo();
        this.setState(info);
    }

    render(): JSX.Element {
        // Message is reusable component that receives the info through `props`
        return <Message {...this.state} />);
    }
}

С точки зрения проектирования React State должно быть личное к компоненту.Я согласен с этим.Но здесь вся информация о состоянии Public .Что может бросить эту концепцию пути.(Если, например, DATA всегда ведется в докладчике, почему в этом случае он должен быть закрытым?)


OPTION 2 - (Плоское решениеИмея частный реплицированный интерфейс для State)

Говоря с некоторыми коллегами, они утверждают, что мы всегда должны сохранять состояние приватным.Я сразу подумал о создании IMessageViewState, который будет точно таким же, как IMessageInfo.Таким образом, концептуально все будет правильно, но мы получим проблему с обслуживанием (IMessageInfo и IMessageViewState для обновления при изменении некоторых его членов).


ОПЦИЯ 3 -(Составьте IMessageInfo в IMessageViewState. Имеет личное состояние)

Итак, мои коллеги предложили определить IMessageViewState как:

interface IMessageViewState {
    messageInfo: IMessageInfo;
}

Таким образом, мы предпочитаем состав (они говорят).Но я не вижу никакого преимущества в том, чтобы иметь здесь композицию.Вы видите что-нибудь?Например, если какой-либо член IMessageInfo изменится (сообщение или значок), нам нужно будет передать весь объект messageInfo в this.setState(...), вместо того, чтобы, например, только обновить icon.По сути, это была бы более подверженная ошибкам реализация.


OPTION 4 - (Расширение IMessageInfo. Имеет частное состояние)

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

Я думаю, что наследование здесь не дает возврата.


ЗАКЛЮЧЕНИЕ

На мой взгляд, опция 1 - это то, что лучше всего подходит для этой проблемы.Поскольку все члены государства являются публичными, я думаю, что нет необходимости иметь частное государство.Опция 1 обеспечивает чистоту кода.

Хотя, если бы я выбрал решение с частным состоянием, лучше подойдет Вариант 4 .

ВОПРОС: Какое решение будетбыть правильнее?

Ответы [ 2 ]

3 голосов
/ 30 апреля 2019

Я думаю, что здесь есть какое-то недопонимание относительно interface и state.Интерфейс - это всего лишь тип какого-то объекта.Таким образом, у вас может быть отдельный файл, который экспортирует все необходимые интерфейсы для вашего решения.IMessageInfo возможно может использоваться в нескольких местах.

State - объект некоторого типа.Это может быть тип IMessageInfo или какой-то другой.state является приватным для одного компонента.И это будет дизайн Реакта.

Вы можете рассмотреть дополнительную возможность использования Redux, чтобы сделать state центральным для всего решения.В этом случае IMessageInfo может быть экспортировано из части вашего магазина, ответственного за MessageInfo.

Пример

// store/MessageInfo.cs

export interface IMessageInfo { /*...*/ }

const initalMessageInfo: IMessageInfo = { /*...*/ }

export const actionCreators = {
    requestMessageInfo () //...
}

export const reducer: Reducer<IMessageInfo> //...

В этом случае вы (1) сохраните IMessageView sigle через ваше решение, (2) сделаете state на основе IMessageInfo доступным для нескольких компонентоввашего решения.

1 голос
/ 30 апреля 2019

Таким образом, мы предпочитаем композицию (говорят).Но я не вижу никакого преимущества в том, чтобы иметь здесь композицию.Вы видите что-нибудь?Например, если какой-либо элемент IMessageInfo изменится (сообщение или значок), нам нужно будет передать весь объект messageInfo в this.setState (...),

Рассмотрим случай, когда вынужно добавить больше данных во внутреннее состояние MessageView.В этом случае вариант 3 оптимизирован для:

interface IMessageViewState {
    messageInfo: IMessageInfo;
}

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

Если вы на 100% уверены, что IMessageInfo имеет все, что когда-либо понадобится классу MessageView, вы можете перейти с Option1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...