【问题标题】:React/TypeScript: Creating a unified "notification" function that ties to a single componentReact/TypeScript:创建与单个组件相关联的统一“通知”功能
【发布时间】:2018-12-06 16:30:43
【问题描述】:

我正在尝试设计我的应用程序,以便所有通知都绑定到包装应用程序的单个“snackbar”样式组件(我正在使用材料 UI snackbar 组件):

例子

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、react-context)的例子,但我希望避免为此使用全局状态。

我已经尝试遵循一些关于创建 HOC 模式的指南,但我似乎无法设计出符合我想要的工作方式的东西。我正在尝试做的事情在技术上是否可行?我知道我可以通过将函数作为道具传递给每个孩子来完成这项工作,但这需要向每个接口和中间组件添加一个字段,并且不是很干燥。

【问题讨论】:

    标签: reactjs typescript


    【解决方案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),它可能会或可能不会成为未来。

    我曾尝试遵循一些关于创建 HOC 模式的指南,但我似乎无法设计一些东西

    HOC 在这里不起作用。或者所有 JSX.Elements 都需要包装在 HOC 中。并且更容易将回调函数向下传递到整个元素树,而不是使用 HOC。

    【讨论】:

      猜你喜欢
      • 2021-12-07
      • 2013-11-24
      • 1970-01-01
      • 2020-06-18
      • 2018-03-06
      • 1970-01-01
      • 2019-08-13
      • 1970-01-01
      • 2020-12-20
      相关资源
      最近更新 更多