Reputation: 1820
For a single page app using redux as state management and whatever router, imagine:
/user
/
/foobar
etc.In the following examples I use a render prop instead of a HoC but it is not mandatory, WithUser contains request redux actions and selectors and User, Foobar contain all required redux actions
pro: no duplications, only one render
<WithUser render={user => (
<PageLayout user={user}>
<Route path="/user">
<User user={user} />
</Route>
<Route path="/foobar">
<Foobar />
</Route>
</PageLayout>
)} />
pro: ?
cons: user is fetched every time page change
// App.jsx
<div>
<Route path="/user">
<User />
</Route>
<Route path="/foobar">
<Foobar />
</Route>
</div>
// User.jsx
<WithUser render={user => (
<PageLayout user={user}>
{this.renderUser(user)}
</PageLayout>
)} />
[edit:] solution added after the answer of @germanwebdev
pro: separation of concerns
cons: duplication of requests
// App.jsx
<PageLayout>
<Route path="/user">
<User user={user} />
</Route>
<Route path="/foobar">
<Foobar />
</Route>
</PageLayout>
// PageLayout.jsx
<header>
<WithUser render={user => (
<Menu user={user} />
)} />
</header>
// User.jsx
<WithUser render={user => (
<section>
{this.renderUser(user)}
</section>
)} />
Upvotes: 0
Views: 202
Reputation: 11
I think it is a valuable practice to dissociate components lifecycle to data lifecycle. It seems your are trying to find a React architecture to fit your data lifecycle (how to prevent multiple calls? how to optimise renders assuming my component fetch the data on mount?) whereas the components architecture should instead focus on answering questions React was designed for : Is the component a clear view of the current state of the data ? Is each component respecting the single responsibility principle (replace with the design pillar of your choice) ?
With this in mind, your components should only focus on describing accurately how to render the current state of the data, no matter the logic used to fetch, transform, or cache the data.
This goes in favor of the "connected components when required" way of building the App. You state in comment that it adds complexity, I think :
- it creates complexity where it needs to be, in some data management logic outside of React, which is never simple anyway so it have to be handled exhaustively;
- it simplify the use of the data, leading to component that are more clear and self-contained.
To sum up: you should not try to solve a data management problem using a specific React architecture, but instead think the data without React at all, then use the well-know connector pattern to update view when data updates. The "connected components when required" example would be the way to go.
Upvotes: 1
Reputation: 26
The first solution kind of defeats the purpose of having the state handled by redux. It's probably not so obvious in such a small example, but it will become obvious in more complex applications pretty quickly. Passing down state through a deeply nested component tree gets really tedious.
One of the main (and probably biggest) pro for the second variation is that only components that really care about the user data need to be connected to the redux state, and only those will re-render when the state changes. In your first example this would be the application root, which means every time something in redux changes your whole app re-renders.
Upvotes: 0