Я пытаюсь спроектировать свое приложение так, чтобы все уведомления были привязаны к одному компоненту стиля «закусочная» (я использую компонент «Закусочная панель материала»), который обертывает приложение:
пример
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, но, похоже, я не могу разработать что-то, что работает так, как я хочу, чтобы это работало. Возможно ли то, что я пытаюсь сделать, технически? Я знаю, что мог бы выполнить эту работу, передав функцию каждому дочернему элементу в качестве опоры, но для этого требуется добавить поле к каждому отдельному интерфейсу и промежуточному компоненту, и это не очень СУХОЙ.





В 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.