I have a component which contains several nested child components; these children require information about the parent component, as well as data from my redux store. Given their quantity, is it better performance wise to use the useSelector hook once within the parent component and pass it down through attributes (rather than context), than it is to have each child use useSelector? Additionally, is it better to pass information about the parent component through its attributes, than it is to have each child use useContext?
edit: in testing, there is a 20% increase in speed when passing through attributes; my guess is useSelector/useContext is more costly in its declaration than an attribute? Can anyone confirm this to be true?
is it better performance wise to use the useSelector hook once within
the parent component and pass it down through attributes (rather than
context), than it is to have each child use useSelector?
The second one is a better choice. You will have less unnecessary re-renders compare to the first choice.
In your first choice scenario, when something in the parent is changed, it will trigger the re-render for the component (means, the children will be affected).
is it better to pass information about the parent component through
its attributes, than it is to have each child use useContext?
The answer is same with the above.
As you can see react-redux uses context API
https://github.com/reduxjs/react-redux/search?q=useContext&unscoped_q=useContext
In terms of performance, all the above approaches are close to each over.
The best way to deal with performance issues is the following:
Wite good-quality code (number of args per function, number of lines per module, cyclomatic complexity, block nesting, fan-in/fan-out coefficients and so far and so on). Do not take into account performance issues.
Profile and find out bottlenecks in your good quality code. Prioritize them.
Fix found issues https://en.reactjs.org/docs/optimizing-performance.html
Related
can I use Use state instead of redux?
Can I Manage all the state by use state ?
This question has a long and complicated answer, but I would suggest the first port of call would be reading up on the redux docs about how you might want to organise the state within your application.
TL;DR, it entirely depends on your situation, take a look here
Both are valid, but both have cases where they are better to be used, for example if you have a state you want to manage one level below, and is not used by other components on different hierarchy, then passing the state and it's handler as a prop is the better solution.
But some cases are more complex and require a lot of passing down of a prop through the components until it reaches the child that actually uses it, and. the parents of that child do nothing but pass it down, that is a smell of bad code.
Here it is beneficial to have it in a global state where the child can access it directly, without needed all of its predecessors to pass it down as a prop (also known as prop-drilling). Another case where this is useful is when multiple components need to access the same state, in different part of the system. It would be much cleaner to have it stored in a global state available for every component that requires it.
TL;DR, depending on your case, one solution is better than the other. Assess your situation case-by-case.
I am working on a React app, and I need to modify the parent's state from a child component. Of course, I could simply write a function in the parent, and pass it as a prop to the child (like everyone else seems to be doing). However, I tried instead to pass the entire parent as a prop to the child, so that the child can freely modify the parent's state.
This is how my parent looks with its children:
{this.state.entries.map(entry => (
<UserEntry
...
mainThis={this}
/>
))}
Notice how I pass the entire parent into the child as a prop with a this. From my child code, I can then modify the parent's state with a simple this.props.mainThis.setState().
Of course, this worked, and I am really pleased with myself. However, I am wondering why people are not doing this. Would it affect performance in the long run, or something?
As your codebase grows bigger and more complex, you will find yourself trying to find a way to manage the complexity. It is important for reducing bugs and adding new features. Doing this opens up a can of worms.
Heres an example. You do this in one parent to child. The child also has a list of elements that it passes the this reference to. Finding out which child element is updating the state that causes a bug from data becomes a chore. You won't have a good place to drop a debug point to see values, and the job will be harder
A big advantage of React is the idea of a component. React makes the component re-usable and self contained. If you start passing the this reference, your parent component becomes tightly coupled to the child component. It becomes harder to tease apart the functions of each component.
Feel free to experiment with this pattern. When the codebase reaches the tipping point, you will feel the pain of this design choice very quickly.
I am wondering why people are not doing this. Would it affect
performance in the long run, or something?
It will make your code hard to debug, understand and test because of tight coupling between parent and child. This is also against encapsulation principles because a child component shouldn't know anything about state and internal implementation of parent component and vise-versa. Components should be loosely coupled.
This has nothing to do with code performance but it will surely affect performance of you team in the long run.
Bonus Read: 7 architectural attributes of a reliable react component
As I see it, I could make my entire app a presentational/dumb component and then have a single container component pass the appropriate props.
On the other extreme, I could make every single component smart.
So, is there a rule of thumb to decide when to make your presentational component smart?
Quoting from Presentational and Container Components by Dan Abramov:
When to Introduce Containers?
I suggest you to start building your app with just presentational components first. Eventually you’ll realize that you are passing too many props down the intermediate components. When you notice that some components don’t use the props they receive but merely forward them down and you have to rewire all those intermediate components any time the children need more data, it’s a good time to introduce some container components. This way you can get the data and the behavior props to the leaf components without burdening the unrelated components in the middle of the tree.
... This is an ongoing process of refactoring so don’t try to get it right the first time.
I would argue that there should be a nice balance between the size/complexity of the app and the number of smart components (containers).
Consider introducing a container when:
The hierarchy becomes too deep and passing props around becomes a hassle.
It is likely that an entire feature (UI + data mapping) will be moved/re-used across the app.
There's a need to encapsulate a feature for reasons such as the above or any other (versioning, security, lazy-loading etc.)
You identify unnecessary updates as a result of data mapping.
On the other hand, consider sharing a container when:
Multiple components use data of the same nature and form a single unit that might be considered a "feature".
Mapping (mapStateToProps/mapDispatchToProps) becomes repetitive amongst multiple proximate components.
Also, keep in mind that refactoring might be necessary as your app evolves.
As a react web app gets complex, some components have a number props, which is less readable, harder to expect what this component does, and tedious to add lots of prop types checks and pass props from top-most component to bottom. This is mostly caused by passing flux/redux actions and stores passed from top to bottom.
Is there a great way to reduce the number of props passed in?
There are two solutions I thought of, which are not perfect:
Pass props with a spread operator {...props}. This does reduce writing a number of props and prop type checks, but there may be conflict in naming, so the names of actions/stores should be unique. Another downside is to be extra careful of what props to pass or not to avoid side effects.
Wrapping the component with a container which directly connects actions/stores to the component, in an hoc-fashion. For example, react-redux's connect() can be used. This is cleaner and simpler than Solution #1, but it's hard to write component tests if the component contains a container because of a Redux error.
One example of the error is
Invariant Violation: Could not find "store" in either the context or props of "Connect(Header)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(Header)".
You've described two approaches and their pros and cons pretty well. I'll add a few design considerations to what you've said.
Approach #2 is my preferred approach. Reducing the amount of props passing through the components avoids complexity. There are ways to test components without triggering that error, but I think that deserves its own separate Stack Overflow question, to honest. For now, I'll just say look into shallow rendering, and consider whether you really need to just do unit testing here vs integration testing. If you will also be creating automated tests in something like Selenium, then that can serve as your integration testing, perhaps.
Approach #1 can be improved by making scrupulous use of PropTypes to validate what is being passed through. It's reasonable to leave out the PropTypes checking on the middle components that are just passing ...props through, but the end components (components that actually use the props instead of just passing through) should have really stringent PropTypes declarations. Use Shape instead of Object. Use ArrayOf instead of Array, and basically take all opportunities to be specific in your PropTypes declarations.
Regarding your concern about name conflicts, it sometimes helps to group props together as members of one object and pass that object as a single prop. If the props are conceptually related or have a single destination component, this makes some sense. I still greatly prefer just having more container components (approach #2) since it causes less information to flow through props. And writing good PropTypes for objects with nested members takes a little more time and yields warning messages that take longer to troubleshoot.
People sometimes forget about .state after they start using Redux/Flux, with some purists preferring to send and receive everything through the store. The elegance of the stateless component declaration further biases me against adding .state to a component. But .state is great for tracking ephemeral things like animations and tooltip visibility. Not everything needs to be in the store and pass through props.
I'm using the ES6(?) decorators with Redux and React. In many examples I see people explicitly assiging which store items get passed as props. In some examples I see people using spread attributes to just pass everything through like:
#connect((store) => {
return {
...store
}
})
export default class SomeComponent extends React.Component {
...
Is it okay to just do this for every component, or should you cherry pick the props specific for that component?
There is a huge performance detriment, as on every action dispatch react-redux runs every connected component's mapStateToProps, and then shallowly compares the old props to the new props. If there's any change the wrapped component will re-render. Basically if you pass in the entire store, every connected component will re-render on every action dispatched.
Yes, there are. It's not as easy to read what props the component is actually using. Also, props that you aren't using in the component can change and will trigger unnecessary re-renders.
I went thru both paradigms of redux development.
Every component gets all the actions, and all of the state.
Only the container/parent/base pages get all the actions/state
Gives the children only what it needs
What I found. Yes, there is a performance hit because if every component has every state property, imagine you change one state value - every single component gets that update - whether it needs it or not. Constant updates.
All night you are woken up:
Imagine your dog wakes up at 3:30am every night to go outside to pee.
Imagine your neighbor wakes up at 4am for work.
Imagine your other neighbor wakes up at 4:30 am for work.
Imagine your family wakes up at 5:15 am for work.
And you need to get up at 6:00am work.
In all of those scenarios, you are woken up. Over time, how effective are you gonna be at work? You are gonna be tired, sluggish etc...
Now, imagine - you CAN only ask to be woken up, when you need to be? And not all those other times, that have nothing to do with you?
That is how I think of it. So, let your child components only know about the things they care about.
So, I usually have the container page/parent - know about everything - and hand down what it needs.
Caveat - I have found, there are some cases in which a child component (for whatever reason) needs to know about nearly everything. For me, passing every single thing down to multiple levels - also impacts those children you pass along the way...
parent --->
child (just care about one thing) --->
child (just care about one thing)--->
child (I want alot of stuff)
I don't like to pass all that stuff down all those children, especially if those children higher up the ladder don't care. So, in that deepest most child, I give it everything from the get go - and not pass anything to it.
That is a little bit of a performance hit, I'll take to make the code cleaner.
But overall, don't give every component everything. Makes a huge performance difference overtime, and as your application grows.