Let's say I have a really dumb component A. I don't want any of the rendering logic from data to go in this component. Just take some raw data and display it.
Which is the more react way of going about this?
Creating just a bog standard factory function, that given different flags will create a new component with different props set
Making a wrapping component which does all the logic and sets the correct props from the data.
My fear with creating a wrapper is it is just more bloat in the chain of components. When this feels more a tangent.
Actually separating logic from presentation is pretty usual in React and considered best practise. So solution 2 is the way to go.
Your component A would then probably be a stateless function http://facebook.github.io/react/docs/reusable-components.html#stateless-functions whereas it's father would have only logic methods.
For your information, such a scheme is also the default way of using redux store, see http://redux.js.org/docs/basics/UsageWithReact.html#presentational-and-container-components
Related
I'm working on a part of a React app in which a high-level component creates and passes certain props down through a few layers of components that don't use them to a final component that does.
When validating props with propTypes, is there a good reason to list these props to be checked at every level, going down through the layers? Or is it acceptable to check them only in the final component that uses them?
It seems to me that the former method is redundant; the latter seems to make more sense to me, but I'm curious if there is a reason why I ought to do the former. I haven't seen any discussion on it, which could mean it's an unimportant question, but I'd be interested to know.
I agree with you about if you use props only for dril down for children in the tree, it can be done only once at the leaf components, where you realy use this data. I recently find out that one more place is important for props validation: the components which fetch data from out of app scope, such as backend, because sometimes the structure of the data changes or the data types, then it will be dificult to find which part is broken without props validation.
I'm pretty new to Redux and would like to use it my application but I'm stuck at architecture/design phase for the Redux part. Here are my requirements and my suppositions regarding the design.
Application details:
SPA with AngularJS. Other libs used ng-redux, reselect, rxjs.
Component details:
Re-usable grid component to render huge amounts of data.
My idea:
Create a plug-n-play kind of component-based architecture, where all the internal components of the grid are independent of the parent/composing component like search, sort, row, header, cell.
All the components will have their own set of reducer, action, selector, and slice of state from the store.
Because all the components have their own reducers and can be plugged-in on demand, I need them to be lazily registered to the store instead of being accumulated in one place.
Some of the components like search, sort along with having their own state, also can affect other components state. Ex: setting up of query parameters (searchText, sortOrder etc.) to fetch the grid data which would be handled by another component(s).
My thoughts:
For the 1st point, I'm looking into reselect for supplying the dependent slice of state.
For the 2nd point, I'm still confused about which to use combineReducers/replaceReducer for the lazy registration. I feel combineReducers will not fit if I want access to multiple parts of the state.
For the 3rd point, I'm thinking of following approaches:
a. Passing entire state via getState() wherever required to update multiple parts of the state. Though this approach gives me feeling of improper use of Redux.
b. Component A fires its own action which updates their part of the state, then another action is fired for the other component B to update its slice of state. This approach as well feels like breaking the whole idea of Redux, the concept of side-effect could be used here though I don't know how to use it, maybe redux-saga, redux-thunk etc.
NOTE: Use of either of the approaches shouldn't lead to the component knowing about the other components hence whatever has to be done will be done by passing a generic config object like { actionsToFire: ['UPDATE_B'] }.
I need state management while navigating back and forth between the pages of the application, but I don't require hot-reloading, action-replay, or pre-fetching application state from server-side.
Components will also be responsible to destroy their state when no longer required. And state will have a normalized structure.
I know the requirements might seem weird or not-seen-often but I would keep them that way.
Few things I already know are:
I don't need to use Redux like the classic article from Dan says, but I think I need it here in this case.
I know about the Smart and Dumb components, mostly my components might seem smart (i.e aware of application state) but that is how I want to keep them, I might be wrong.
Diagram of the grid component:
Grid Component Diagram
Redux's global store makes encapsulation and dynamic plug-and-play behavior more difficult, but it is possible. There's actually many existing libraries for per-component-instance state and dynamic registration of reducers. (That said, the libraries I've seen thus far for component management are React libraries - you'd have to study some of those and reimplement things yourself for use with Angular.)
I'm new to React and trying to get how to build a good app architecture with it.
I also use typescript with all that features: interfaces, async-await, generics, etc. So, I'm puzzled about implementing some patterns:
1) Dependency Injection and reusable component instances
The first thing I can't get through is DI. Let's say we got a component class UserProfile that requires some dependencies like UserProvider. It would be perfect if the component instance (with deps injected) could be reusable, but I'm afraid it's only my dreams, not the react guys'. :)
So, I'm supposed to place this component this way:
<UserProfile id={123} />
Ok, what's the proper way to inject the dependency here? As an attribute like this <UserProfile id={123} dependency={userProvider: userProviderInstance} />?
Don't you think it is weird to put component input data, options/parameters and dependencies all together? I'd be happy if I could clearly separate them and put generic restrictions on the component class. What's the best practice?
Another side of impossibility to reuse component instances is the fact we must carry some needless objects through all the components structure just to inject them somewhere deep at the bottom. And nobody tells you what component does really use them. And try to imagine what adding a dependency to a low-level component will take in a large project. I just can't.
2) Using Promises
Let's consider a simple component that is supposed to render a counter: <Counter value={123} />.
Now, value is got from some API by calling a method getCounter(id: number): Promise<number>;, so the obvious way to put all together could look like this:
<Counter value={await provider.getCounter(id)} />
But i't impossible, I know. The common practice tells us to make it through setState method and rerender the component after the value is received.
Now imagine that the parent component is pretty complex and has many different providers. So, the parent component may not have definite state typing. It also may be conditional, you know...
You could suggest me implement the async getting in the Counter component, but i will refuse for a simple reason: That component does not know anything about the value's origin. In other cases the value is passed directly as a number. So, do you got better ideas how to keep code clean and simple while using promises?
Please, let me know if you come across some good articles or have your own experience in solving these issues.
PS: Thanks for attention! :)
This topic is a subject of bias - so below I will give my very personal thoughts on the topic that does not pretend to be absolute truth.
DI.
This is indeed not so common pattern in react as it is in angular. But having both context and properties in components allows you to archive the same level of separation as with pure DI. Check the context - it will help you to get rid of passing same props through the whole component tree. There are quite a few articles on this topic already (one, two) - check them out. Also you might be interested in reading this thread).
Promises
I do not really see any problem here. React has a simple concept - basically you have state and based on this state your app can render itself. Whereas rendering is not async operation - the preparation/update of the state can easily be done asynchronously and after results are assigned to the corresponding parts of the state - the necessary child components will be updated automatically. If you component has no knowledge of how to obtain value - it should not try to do it in first place - value should be passed down as props.
When passing data between two elements that are very far away from each other in the hierarchy of components, passing data through props can be tedious. In these use cases I've resorted to using Redux just because it is less to keep track of when there is a large amount of components.
What I've done in one little project is to use a closure to encapsulate state and export that variable and consume it elsewhere. I feel this is a an antipattern but it does work.
The way it works is by declaring some variable that is going to be modified within a component. This same variable is the imported from elsewhere and consumed from elsewhere.
Here is a small sample with what I am doing (just pretend there is a large component hierarchy): https://codesandbox.io/s/2R9RvYkN1
So my questions are: is there a better way to achieve the same results? Should we use a Flux implementation for these use cases? Is it ok to just pass props around through a large hierarchy of components?
As you stated yourself, redux solves this problem by providing an "App state" that's global to your app, which allows you to connect any component you want to that state.
Your "closure" is merely a poor-man's Redux, it's also a global state, only it lacks any of the features provided by Redux(unless you write them specifically).
let's CompA needs to re-render based on a click event on CompB, how do you do that automatically with a closure? you'd have to add listeners, check if a relevant state was changed and then re-render.
all these things are done for free by Redux, so I don't see any added benefit(except for not using redux, which can be a benefit in it's own).
If it's that important not to use redux, this can be "fine", yet very dangerous and I'd say it won't scale well.
Redux is all about reducer composition. You can nest them and combine then however you like. The important thing is that each reducer is totally unaware of the outer structure of the state. It only handles its own piece.
Unfortunately, this doesn't apply to components.
When you connect a component to redux, you usually define a function that maps the state to the component's props. What I don't find optimal is that this function always gets the whole app state as an argument.
In an ideal case uf a component depended on data managed by a single reducer, I'd prefer if the component (or the connect function)...
had access only to that data.
didn't have to worry about where the data is located in the state's hierarchy.
The whole component (or perhaps an app module/section) would be nicely decoupled from the rest of the app (which I think is the ideal that React has been striving for since the beginning).
If nothing else, it'd make refactoring of the state's structure way simpler (right now it's easy to move around nested reducers but then you have to manually update all those so called ContainerComponents to match the new state structure).
Is there a recommended way or perhaps a pattern how to achieve this kind of decoupling on the component level?
Apparently, the answer is reselect. The selectors can be structured and nested the same way as the reducers.