-
-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Description
I'm curious about best practices for my use-case (which I believe is probably very common). It's combination of react
, redux
, react-router
but I believe the discussion is best suited for redux
Documentation and guides are very vague when it comes to component-to-component communication (of a non parent-child nature). Imagine using react-router
where the overall page is derived of nested layout components such as
ReactDOM.render((
<Router>
<Route component={DefaultLayout}>
<Route path="foo" component={FooLayout}>
<Route path="products" component={Products}>
<Route path="users" component={Users}>
<Route path="widgets" component={Widgets}>
</Route>
</Route>
</Router>
), document.getElementById('app'))
DefaultLayout
looks like this:
export default React.createClass({
render: function() {
return (
<div className="default-layout">
<div class="receive-any-component"></div>
<main>
{this.props.children}
</main>
</div>
)
}
})
For the sake of this example, FooLayout
(loaded into this.props.children
) can be any sub layout you want to imagine.
All three routes: /products
, /users
, or /widgets
have a button in their component. When clicked, it will load a whole new component into the DefaultLayout
's <div class="receive-any-component"></div>
section. For example
Products
component:
import store from 'path/to/store'
export default React.createClass({
render: function() {
return (
<div className="product">
Lorem ipsum...
<button onClick={this.onClick}>Click Me</button>
</div>
)
},
onClick: function() {
// There are several ways to have a component loaded DefaultLayout's
// div.receive-any-component
}
})
This whole example is over simplified. I'm using react-redux
in the real thing. Official react docs only say one small bit on this type of use-case:
For communication between two components that don't have a parent-child relationship, you can set up your own global event system. Subscribe to events in componentDidMount(), unsubscribe in componentWillUnmount(), and call setState() when you receive an event. Flux pattern is one of the possible ways to arrange this.
So, I understand that I can use Redux to dispatch info whereby DefaultLayout
is subscribed, but I need to load a whole component into DefaultLayout
. It would seem to me there are two basic options, neither of which I feel are correct.
Option One
Have our Product
component dispatch the component we want to load:
import store from 'path/to/store'
const componentToLoad = (
<Whatever />
)
export default React.createClass({
render: function() {
return (
<div className="product">
Lorem ipsum...
<button onClick={this.onClick}>Click Me</button>
</div>
)
},
onClick: function() {
store.dispatch({
type: 'LOAD',
component: componentToLoad
})
}
})
Ultimately, I'd like the DefaultLayout
to be unaware of what components it's loading, so this solution works out in that regards. But sending a component into redux
just seems so wrong, but it works.
Option Two
Instead of dispatching a component, dispatch some state that indicates which component should be loaded. In this case, it would seem that DefaultLayout
would have to import
every possible component it might need to load (which in my real usecase is many), then subscribe to our state and use a switch statement to determine which one of our loaded components should be placed into .receive-any-component
. This feels better from the redux
end but feels crappy that DefaultLayout
is aware of every possible component that it might need to load.
I'm not new to JS, but somewhat new to React/Redux. What am I missing?
And I apologize this question is so long. It's difficult for me to describe this any other way