React / TypeScript: создание единой функции «уведомления», которая привязана к одному компоненту

Я пытаюсь спроектировать свое приложение так, чтобы все уведомления были привязаны к одному компоненту стиля «закусочная» (я использую компонент «Закусочная панель материала»), который обертывает приложение:

пример

class App extends React.Component {
  public render() {
    return (
      <MySnackbar >
        <App />
      <MySnackbar />
  }
}

усеченный пример класса закусочной:

class MySnackbar extends React.Component<object, State> {
  public state = {
    currentMessage: { message: "", key: 0},
    open: false
  };
  private messageQueue = [];

  public openAlert = (message: string) => {
    this.queue.push({ key: new Date().getTime(), message})
    if (!this.state.open) {
      this.setState({ open: true });
    }
  }
  // other class methods...
  public render () {
    // render component here...
  }
} 

Я пытаюсь понять, как сделать так, чтобы я мог просто экспортировать функцию, которая при вызове имеет доступ к функции «openAlert», ссылающейся на родительскую закусочную.

гипотетический дочерний компонент:

import notificationFunction from "MySnackbar";

class Child extends React.Component {
  public notifyUser = () => {
    notificationFunction("Hi user!")
  }
}

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

Я пробовал следовать некоторым руководствам по созданию шаблонов HOC, но, похоже, я не могу разработать что-то, что работает так, как я хочу, чтобы это работало. Возможно ли то, что я пытаюсь сделать, технически? Я знаю, что мог бы выполнить эту работу, передав функцию каждому дочернему элементу в качестве опоры, но для этого требуется добавить поле к каждому отдельному интерфейсу и промежуточному компоненту, и это не очень СУХОЙ.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
388
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В Stable React это делается с помощью Context (https://reactjs.org/docs/context.html).

interface IContext {
  updateMessage: (newMessage: string) => void;
}

interface IProps {}

interface IState {
  message: string;
}

const SnackbarContext = React.createContext<IContext>({
  updateMessage: () => {},
});

class Snackbar extends React.Component<IProps, Partial<IState>> {
  constructor(props) {
    super(props);
    this.state = {
      message: "",
    };

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

  render() {
    return (
      <SnackbarContext.Provider value = {{ updateMessage: this.updateMessage }}>
        <div>
          <strong>MESSAGE:</strong> {this.state.message}
        </div>
        <hr />
        {this.props.children}
      </SnackbarContext.Provider>
    );
  }

  updateMessage(newMessage: string) {
    this.setState({ message: newMessage });
  }
}

class Child extends React.Component {
  static contextType: React.Context<IContext> = SnackbarContext;
  context: IContext;

  constructor(props) {
    super(props);

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

  render() {
    return (
      <div>
        <button onClick = {this.onButtonClick}>Create message</button>
      </div>
    );
  }

  onButtonClick() {
    this.context.updateMessage(`Message with random number at the end ${Math.random()}`);
  }
}

<Snackbar>
  <Child />
</Snackbar>

Есть также эксперимент с крючками (https://reactjs.org/docs/hooks-intro.html), который может быть, а может и не быть в будущем.

I have tried following some guides on creating HOC patterns, but I can't seem to design something

HOC здесь работать не будет. Или все JSX.Elements нужно будет обернуть в HOC. И легче передать функцию обратного вызова по всему дереву элементов, чем использовать HOC.

Другие вопросы по теме