可多次创建的React.js“全局”组件

时间:2018-08-31 08:27:53

标签: javascript reactjs

我无法解决这个问题。

问题:假设有一个应用程序,并且可能要通过代码创建某种通知/对话框/等。

我可以拥有“全局”组件并对其进行管理,但是这一次只能将我限制为一个通知,这不合适。

render() {
  <App>
    // Some components...
    <Notification />
  </App>
}

或者我可以通过组件Notification本身来管理多个通知。但是状态管理尚不清楚。

另一个问题是,如果我从该组件中获得某种形式的用户确认(如果是确认对话框而不是简单的通知),则使用此解决方案将不太方便。

另一种解决方案是手动渲染组件。像这样:

notify(props) {
  const wrapper = document.body.appendChild(document.createElement('div'))
  const component = ReactDOM.render(React.createElement(Notification, props), wrapper)
  //...
  // return Promise or component itself
}

所以我叫:

notify({message: '...'})
  .then(...)

或:

notify({message: '...', onConfirm: ...})

这个解决方案似乎很笨拙,我想让React处理渲染,而且我还有一个多余的div。另外,如果React API更改,我的代码也会中断。

此方案的最佳做法是什么?也许我错过了完全不同的东西?

1 个答案:

答案 0 :(得分:2)

您可以为此使用React Context

您可以在应用程序中高层创建一个React上下文,然后将一个值关联到它。这应该允许组件创建通知/与通知进行交互。

export const NotificationContext = React.createContext({
  notifications: [],
  createNotification: () => {}
});

class App extends Component {
  constructor() {
    super();

    this.state = {
      notifications: []
    };

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

  createNotification(body) {
    this.setState(prevState => ({
      notifications: [body, ...prevState.notifications]
    }));
  }

  render() {
    const { notifications } = this.state;

    const contextValue = {
      notifications,
      createNotification: this.createNotification
    };
    return (
      <NotificationContext.Provider value={contextValue}>
        <NotificationButton />
        {notifications.map(notification => (
          <Notification body={notification} />
        ))}
      </NotificationContext.Provider>
    );
  }
}

通知存储在一个数组中,一次允许多个。目前,此实现永远不会删除它们,但可以添加此功能。

要创建通知,您将在应用程序内使用相应的上下文使用者。我在此处添加了一个简单的实现用于演示。

import { NotificationContext } from "./App.jsx";

const NotificationButton = () => (
  <NotificationContext.Consumer>
    {({ notifications, createNotification }) => (
      <button onClick={() => createNotification(notifications.length)}>
        Add Notification
      </button>
    )}
  </NotificationContext.Consumer>
);

You can view the working example here.