Is it better to send redux state down to children as Props or for the Children to directly read from redux state? - redux

I realize this is a fundamental question that may have been answered before, but I'm looking for a definitive answer, with perhaps some reasoning, as I've not quite found one that convinces me that there is better/best/preferred way to do handle this.
Scenario: A dashboard component receives redux state via connect. Some of the data is shared across the dashboard and its children. Some of the data is specific to the dashboard's children.
Question: Should I always pass the props down to the child components (something) like the below, or should I always connect the child components to redux and read the needed data directly from redux state?
import React, { Component } from "react";
import { connect } from "react-redux";
import ChildOne from ".ChildOne";
import ChildTwo from ".ChildTwo";
class DashboardExample extends Component {
render() {
const { sharedData, childOneData, childTwoData } = this.props
return (
<div>
<h1>{sharedData.selectedDate}</h1>
<ChildOne sharedData={sharedData} childOneData={childOneData} />
<ChildTwo sharedData={sharedData} childTwoData={childTwoData} />
</div>
);
}
}
const mapStateToProps = state => ({
sharedData: state.dashboardData,
childOneData: state.childOneSpecificData,
childTwoData: state.childTwoSpecificData,
});
export default connect(mapStateToProps)(DashboardExample);

As Dan Abramov said, it’s nice to have a division between Presentational Components and Container Components.
Presentational Components
Are concerned with how things look.
May contain both presentational and container components** inside,
and usually have some DOM markup and styles of their own.
Often allow containment via this.props.children.
Have no dependencies on the rest of the app, such as redux actions
or stores.
Don’t specify how the data is loaded or mutated.
Receive data and callbacks exclusively via props.
Rarely have their own state (when they do, it’s UI state rather than
data).
Are written as functional components unless they need state,
lifecycle hooks, or performance optimizations.
Container Components
Are concerned with how things work.
May contain both presentational and container components** inside but usually don’t have any DOM markup of their own except for some wrapping divs, and never have any styles.
Provide the data and behavior to presentational or other container components.
Call redux actions and provide these as callbacks to the presentational components.
Are often stateful, as they tend to serve as data sources.
Are usually generated using higher order components such as connect() from React Redux, createContainer() from Relay, or Container.create() from Flux Utils, rather than written by hand.
source post
————————————
Specific answer to your question:
I find it helpful to try and stick with the principles stated above. It makes your code easy to reason about and it helps to separate concerns (Views / Business logic).
But, if you find yourself writing spaguetti props to stick to it, or if it doesn’t feel natural in a specific piece of code, just connect your Presentational Component.

Related

Handling unexpected mutations properties in Vue3js

I have a vue3 webapp that I use to edit some multi-pages documents.
All the pages are stored in a state with pinia. My pinia state is an object with a pages property that is an array containing all the data of each page.
Each page of each document use a specific template, so I created multiple components to handle each template, and I also have subcomponents for some parts that can be found across multiple templates.
I loop through the pages with a root component, passing a reference to the page object, like it :
<PageWrapper v-for="page in pages" :key="page.id" :page="page" />
Then, inside the PageWrapper component, I use the according page template's component, passing along a reference to the page object (the same with subcomponents if any) :
<PageFirst v-if="props.page.type === 'first'" :page="props.page" />
<PageServices v-if="props.page.type === 'services'" :page="props.page" />
<PageTotal v-if="props.page.type === 'total'" :page="props.page" />
<PageContent v-if="props.page.type === 'content'" :page="props.page" />
I wonder what would be the best way to edit a property of my page object from a subcomponent, as I know that it is a bad practice to mutate the property directly.
Do I have to use events ? Is PageWrapper the good place to catch all the events and the modifications?
Any advice on this matter would be of great help to me.
Thanks a lot for your help!
As the Vue official document point out:
In most cases, the child should emit an event to let the parent perform the mutation.
So the answer is you should let the parent do the job of mutating the props. And it will never be a bad solution.
But, look at your design. Your parent component PageWrapper works just like a wrapper. It does nothing but a container for its child.
The props one-way data flow prevents child components from accidentally mutating the parent's state, which can make your app's data flow harder to understand. But if the parent does not actually handle state and your child component's data does not relate with each other, mutating the props inside the child component will be fine.

redux causing component re-rendering

I have a component which is connected to global store and getting some data from the global store. from some portion of this data is sent to another component via props and inside that component i have generated required jsx based on data. Also inside the child component mapdispatchtoprops is also used and it is also connected to global store as well.
The problem case scenario is child component re-renders depends upon the global store data.
The key for global store is like -
foods : {
'list' : '',
's' : '',
fetching : 0,
slist : '',
category : '',
cproducts : ''
}
I guess what happening is the child component is re-rendered 7 times because the number of keys inside global store for foods is 7. if anyone is interested he/she can share his/her views
Components have a render method which returns the JSX markup that it renders to the DOM. For change detection, React use a local state, which is only local to a component, when the state changes the component and its children are re-rendered to update the UI of the changed state.
A quote from the React documentation:
These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate. However, you may still specify .propTypes and .defaultProps by setting them as properties on the function, just as you would set them on an ES6 class.
PURE COMPONENT is one of the most significant ways to optimize React applications. The usage of Pure Component gives a considerable increase in performance because it reduces the number of render operation in the application.
So change your app to be like this
import React, {PureComponent} from 'react';
class Sample extends PureComponent {
render() {
return (
<div>your structure here</div>
)
}
}
export default Sample;
Please read more on react PureComponent. here

redux and listening to scroll events

Building a performance sensitive Redux app that needs to listen to scroll/mouse events throughout a user session.
Plain english implementation would be:
"When component A is in the user's viewport, dispatch FOO action"
From my understanding, the function calculateViewPort + the comparison checking would need to be conducted in the store on every scroll event.
This seems excessive and slow (haven't tested it yet).
Is there another implementation or approach that I have not yet considered?
I was thinking about using something like RxJS for Redux, but want to consider the tradeoff between bringing in a new library for performance and solving it with my existing toolkit.
If there's a saga approach, I'm more open to that too.
There is a InfiniteScroll component. You can refer this and implement in your way or you can use as it is.
Note: this component is not using the redux-saga.
It's better to go with redux-saga as you would take only the response which comes from the latest api call (last mouse scroll) with takeLatest effect.
React Visibility Sensor might be a good choice here. You can wrap the components in VisibilitySensor component and dispatch an action whenever it is on window viewport.
import React from 'react'
import { connect } from 'react-redux'
import VisibilitySensor from 'react-visibility-sensor'
import CUSTOM_ACTION from 'your-actions'
const CustomComponent = (noticeMe, ...children) => {
const handleChange = (isVisible) => { if (isVisible) { noticeMe(); } }
return <VisibilitySensor>{children}</VisibilitySensor>
}
export connect({}, {
noticeMe: () => dispatch(CUSTOM_ACTION)
})(CustomComponent)

What is the correct way to call a component method in many other components in React?

I am using React with Meteor. I am currently building an app that has grown to have a sizeable number of components (some nesting quite deeply, like 5 or more levels).
I often find myself having to pass props from the parent all the way to the children, just to call a component method for a component that has been rendered in the topmost parent, like this:
Parent File
openDialog() {
this.setState({ open: true });
}
render() {
return (
<div>
<Dialog open={ this.state.open } />
<ChildComponent openDialog={ this.openDialog.bind(this) } />
</div>
);
}
ChildComponent
render() {
return (
<div>
<GrandChildComponent openDialog={ this.props.openDialog } />
</div>
);
}
And so on, just to call the openDialog method defined right at the topmost parent.
This works if you only have one branch going deeper inwards. However if you have say, a login modal dialog which can be triggered from many different parts of a site (header, sidebar, inline links, etc), it is obviously impractical to pass in props this way into every single component which could possibly require the link (or not).
What is the correct (recommended) way to handle this kind of issue?
The common solution is to link your component to an external set of actions and an external State Manager. Flux architecure is used for that. And several frameworks, like Redux, help you integrate it with React.
With flux, you can dispatch an action (openDialog for example) from every component without having to pass it through the whole tree of components.

Data model in child component

I would like to know what the best practice is for a communication between parent/child components. I have read this blogpost about communication and components states but haven't found the right answer for my problem.
Following components are considered.
My parent component is a List, which renders several Tasks (child component) from objects in the parent component.
So my questions are:
Is it best practice to pass the object to each Task component?
When a value has changed in the Task component, how does the parent component know about this? Because the parent should know about the infos of all children.
So is this a right pattern to use?
In my Parent Component I have this in the render function:
<Task key={index} taskdata={taskobj} />
My Task child component looks like this:
render() {
return (
<input type="text" name="wunsch" defaultValue={this.props.task.title}/>
);
}
So if the value of the input field will change, does taskobj in the parent component also change? In this example no. But what would be the right pattern here?
Basically when you want to pass information from parent to children you use props, when you want to pass information from child to parent you pass a function to a child as a prop and then call it when you need to update a parent.
You can read more in official docs
Also you can take a look Reflux.
A simple library for unidirectional dataflow architecture inspired by ReactJS Flux
In React, data flows one way
I wasn't really aware of this React concept.
So after reading this link in the ReactJS Doc I decided to the onChange/setState() way as ReactLink is already deprecated.
So when a change in the model happens in the child component I call a method in the parents component to update (setState) my data.

Resources