I have a website with the following react-router
and react-router-relay
setup:
<Router history={browserHistory} render={applyRouterMiddleware(useRelay)}>
<Route path="/:classroom_id" component={mainView} queries={ClassroomQueries}>
<IndexRoute component={Start} queries={ClassroomQueries} />
<Route path="tasks" component={TaskRoot} queries={ClassroomQueries}>
<IndexRoute component={TaskList} queries={ClassroomQueries} />
<Route path="task/:task_id" component={TaskView} queries={ClassroomTaskQueries} />
<Route path="task/:task_id/edit" component={TaskEdit} queries={ClassroomTaskQueries} />
</Route>
</Route>
</Router>
The site is a virtual classroom, in which the teacher can create tasks for the students. These tasks can also be edited.
When a user edits a task in TaskEdit
and hits save, the changes are applied and the user redirected to TaskList
. Now I want to give the user a "Your changes were saved!" message once a task was edited.
I have created a bootstrap alert component (<Alert>
) for this exact purpose.
For illustration purposes, assume I have the following mainView
component (check Router above):
render() {
<div>
<Menu />
<Row>
<Col md={3}>
<Sidebar />
</Col>
<Col md={9}>
{this.props.children} <-- Start, TaskRoot, etc go here
</Col>
</Row>
<Alert someProps={...} /> <-- Popup component
</div>
}
Normally, I would create this alert component outside of the active component and just pass some kind of function that displays the alert as a prop to the active component. Similar to what is shown here.
However, this only works for a specific component. But because <Alert>
sits at the root-level of my page (along with menubar, sidebar, and other things that are static on all pages), I cannot pass this as a prop due to {this.props.children}
.
Allow me to illustrate the flow I want to achieve once more:
<TaskEdit>
.<TaskList>
.<Alert>
to trigger, and show a message.I've seen other solutions suggesting that you can clone all children of a React element and apply the prop needed to open the alert
, but because of the nature of react-router
this doesn't really seem to work.
How can I accomplish the above? Is there a way for a component to be globally accessible? Please note that I don't want to recreate <Alert>
in each component. Only one such component for the whole DOM.
Simple answer:
Put your Alert component once in your top level view, then use some pubsub or event bus lib to update it.
In your Alert component onComponentDidMount function you listen for a specific event and data and update its state accordingly (visibility and message)
In your Task save function you publish your event to the event bus.
More advance answer:
Use a React flux library https://facebook.github.io/flux/docs/overview.html