React: passing data between sibling without causing a rerender - javascript

I have the following problem:
I got an App (A) and a lot of children (B, C, etc).
Now I would like to pass a value from B to C but without any rerender of the whole App. How is this possible?
A (Parent)
|---- B (Child)
|---- C (Child)
|---- D (Child)
|---- E (Child)
|---- F (Child)
I tried to use useContext or a simple callback but in each case the state is hold in A, which, by change makes my whole App to rerender. Any Idea on how to make ii in a proper way?

You can use
shouldComponentUpdate
to avoid this type of scenario. It works for both props and state.
shouldComponentUpdate(nextProps, nextState) {
return this.props.somevalue != nextProps.somevalue;
}
Check if there is any new props passed to the child. If not then the component wont re-render. But avoid using too many children and come up with a better design structure.
Edit:
You can use
PureComponent
as it implements shouldComponentUpdate by default. As mentioned in the doc:
React.PureComponent is similar to React.Component. The difference
between them is that React.Component doesn’t implement
shouldComponentUpdate(), but React.PureComponent implements it with a
shallow prop and state comparison.
If your React component’s render() function renders the same result
given the same props and state, you can use React.PureComponent for a
performance boost in some cases.

The default behavior in React is to re-render on every state change, and in the vast majority of cases you should rely on the default behavior. But when you want to block the re-render of component when the state change and some value from state are passed to child component as props you can take advantage of shouldComponentUpdate
shouldComponentUpdate() is invoked before rendering when new props or state are being received. Defaults to true. This method is not called for the initial render or when forceUpdate() is used.
Lean more here
To block the re-render you should should perform a check in the shouldComponentUpdate to ensure that the previous props and the current one aren't the same. If they are the same. you block the re-render by return false and if they are different you return true which will trigger the re-render.
Or you can use memo

You can use React.memo(component)
This is saved your component from unusual renders.
read this one https://reactjs.org/docs/hooks-reference.html#usememo

Related

Calculation in child components that reflect(Recursively) in parent component

Suppose i have main Parent Component A.
Which has two children B and C components And C component itself a Parent component which also has two children means D and E.
So, If i change calculation in E component that should be instant update in that immediate parent C as well as update in parent A.
So what should be the recursive way that should full fill my requirement.
You're in luck - React was built to solve this problem (among other things). There are two ways React takes care of this for you: Props and State. Props are data passed down from one component to another; they are immutable. State is like an in-memory cache for individual components, and can be passed down to child components as Props. React "reacts" to reassignment of those immutable properties. Any reassignment will cause an updated re-render of your components.
There are two main solutions - the classical React way, and through shared state. The classical React way would be to store the data, and the calculation, in a parent component, and pass a callback down to a child component that would perform the calculation. I.e.:
class A extends React.Component {
constructor(props){
super(props);
this.state = {
number: 0,
};
}
setNumber(number) {
this.setState({ number });
}
render() {
<A />
<B number={number} setNumber={this.setNumber} />
}
}
class B extends React.Component {
constructor(props) {
super(props);
const { number, setNumber } = props;
}
render() {
{number}
<button onClick={() => setNumber(number + 1) />
}
}
This works fine but is not very scaleable. In the structure you provided, you'd have to pass down number and setNumber down a tree of children (sometimes called "prop drilling"). Imagine restructuring a large tree of these children and you can see why this is not a very popular solution.
So, this usually gets solved by creating a shared state that all components can access. React Context can be used for this, and there are also many third-party libraries to this end. Redux is probably the best-known. The goal of all of them is roughly the same - provide a large object of common state that any component can pull from, regardless of its location in the tree. Redux's selectors (for example) are built on the same immutability principle, where reassignment will cause a re-render just as though it was a prop from a parent component.
Some recommended reading:
https://reactjs.org/docs/components-and-props.html
https://reactjs.org/docs/state-and-lifecycle.html
https://reactjs.org/docs/thinking-in-react.html
https://overreacted.io/how-are-function-components-different-from-classes/

How to force react not to re-render children, just receive a state change?

Here's my situation:
shortArray.map(data => (
<div className={this.state.active === data.id ? "show" : "dontShow"}>
{this.processAVeryLongArray()}
</div>
))
I hope you get the idea. Just a state change happens, and processAVeryLongArray is independent from it. The only thing I need the state is to change the classname of an element, but the children doesn't change. By the way, it rerenders all children. How to solve this problem?
The ideal approach is to make the child components Pure Components. If the props to the child components are not changing, the Pure Components will not re-render.
You can use the shouldComponentUpdate(nextProps, nextState) lifecycle hook. You write logic to check the value of your properties and state, after checking you return true to re-render the component, else return false to deny re-rending of the component. Read more about them on their official docs.
or you could use React.PureComponent instead of React.Component, if you want React to handle re-rendering logic by comparing all old and new props and state values behind the curtain.
You can use getDerivedStateFromProps
inside your child component to decide whether each of them should update or not.
Here's also some techniques, best practices and pitfals.

What's the best solution for re-rendering child components on props change in React?

I have a parent component that fetches data in componentDidMount() hook. The state is setState()-d with this data. Then I pass the data to the child components as props and set their state based on these props. On the first render the props will be undefined because componentDidMount() hasn't executed yet. So, the child components get undefined props and the state is created with them. When the data fetches in componentDidMount() new props are passed to the child components, but the state is already created with undefined props and nothing changes. So, I am aware of two solutions now:
Use componentWillRecieveProps(). But this is now deprecated.
Use stateless child components. Pass the data to them as props from
the parent component and don't set a state(use the data from props),
and when the parent does a setState() in componentDidMount(), this
will cause a re-render to child components with new props and
everything works.
Now, what if I want to have stateful child components? I can't use the second method, and the first one is deprecated. What is the best solution to accomplish this?
static getDerivedStateFromProps(props, state)
is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.
This method exists for rare use cases where the state depends on changes in props over time.
static getDerivedStateFromProps(nextProps, prevState){
if(nextProps.someValue!==prevState.someValue){
return { someState: nextProps.someValue};
}
else return null;
}
For more details enter link description here
You can read this blog post.
In short a better approach would be to use fully uncontrolled component with key.
Add a key to the child component based on data. If the data changes, the key changes and child component will re-mount.
Provide data as props to the child, use this props as default state of child component.
Here is a sandbox example
Consider using the replacement for componentDidReceiveProps, getDerivedStateFromProps, if you have state within a component which is informed by the values of the props it receives.
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

how does react detect changes in a component internally?

How does a component gets to know, its props are changed so that it can re-render?
Eg:
function component(props){
return <p>{this.props.childVar}</p>
}
function parentComp(){
let parentVar = 0;
setTimeout(()=>{
parentVar++;
//what happens between: after this statement is executed and till the child component is re-rendered ?
}, 1000)
return <component childVar={parentVar} />
}
One of the most important aspects of React's API is that it is declarative, and that you don't have to worry about when and how changes are being captured and handled.
Basically, each time you call render, a different tree of react elements is being made and React’s diffing algorithm will compare the old and the new tree, and will make the changes if necessary.
From a component point of view, the instance itself does not know about trees, changes and updates. After all it's just a function that returns a react element based on its paramters (props) and local state (if there is any).
You can read more about it in the Docs
In your code snippet the child component will never re-render, because what you do is just change a local variable, and child component will never know about that. So, short answer is component doesn't know is props changed.
There is two reasons for component to re-render:
this.setState was called
A parent component re-rendered

How to handle props changes without using componentWillReceiveProps in React

I've been working on a project which is coded with React. I have a component set that I implemented many components for my own requirements. Many of these act like a composite component. For example, TextBox component which has its own label, own error message mechanism and own input filter etc. Moreover, you know, components have props to manage sth.
Everytime to update my component view (render), I use componentWillReceiveProps and I compare the props changes.
But everytime implementing the componentWillReceiveProps method is so repulsive.
Is there any way to pass props from top to down without using componentWillReceiveProps. I don't want to compare props changes manually. Is there any way to do it automatically.
When I change the props in parent, I'd like to update all views just changing the some prop values from top to down.
I'm not an react expert and performance is not my first purpose also!
One more thing that the answer is not use Redux!
I'm waiting your creative approaches and helpful ideas.
Without seeing the code for the particular thing you're working on, I may be missing something about what you're doing...
As others have commented, React will re-render your component if new props are provided, regardless of whether or not you implement componentWillReceiveProps -- the only reason to implement it is to do some kind of specific comparison or set a state based on new prop values.
From the React docs (emphasis mine):
componentWillReceiveProps() is invoked before a mounted component receives new props. If you need to update the state in response to prop changes (for example, to reset it), you may compare this.props and nextProps and perform state transitions using this.setState() in this method.
Note that React may call this method even if the props have not changed, so make sure to compare the current and next values if you only want to handle changes. This may occur when the parent component causes your component to re-render.
In other words, if you have a component like:
<TextBox title={"Foo"} content={"Bar"} />
That internally passes prop changes on to a couple of child components like:
class TextBox extends React.Component {
render() {
return (
<div className={'text-box'}>
<Title text={this.props.title} />
<Body text={this.props.content} />
</div>
);
}
}
Then each time new props are passed to <TextBox>, <Title> and <Body> will also get re-rendered with their new text props, and there's no reason to use componentWillReceiveProps if you're just looking to update with prop changes. React will automatically see the changes and re-render. And React handles diffing and should fairly efficiently re-render only things that have changed.
However, if you have a separate state value that needs to be set in response to props, for example, if you wanted to show a "changed" state (or whatever) on the component if the new props are different, then you could implement componentWillReceiveProps, like:
class TextBox extends React.Component {
componentWillReceiveProps(nextProps) {
if (this.props.content !== nextProps.content) {
this.setState({changed: true});
}
}
render() {
const changed = this.state.changed ? 'changed' : 'unchanged';
return (
<div className={`text-box ${changed}`}>
<Title text={this.props.title} />
<Body text={this.props.content} />
</div>
);
}
}
If you're trying to prevent re-render in cases where it's unnecessary for performance, do as Andrey suggests and use shouldComponentUpdate: https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate
TLDR; unless you're setting component state from props, there's likely no need to run new props through componentWillReceiveProps
UPDATE Feb 2018: in a future release, React will be deprecating componentWillReceiveProps in favor of the new getDerivedStateFromProps, more info here: https://medium.com/#baphemot/whats-new-in-react-16-3-d2c9b7b6193b
There are few suggestions:
Don't copy props into state in componentWillReceiveProps - just render directly from this.props
If your component need performance tweak (and only if there is problem with performance):
start from using shouldComponentUpdate in generic form like advised here https://facebook.github.io/react/docs/shallow-compare.html
If generic approach doesn't work for you - write custom code
The general approach, how to develop text-box-like components is to keep it stateless.Component renders props directly, and notifies parent component about changes, it don't cares about managing value.
Hope this will help
Please consider pureComponent which by defualt implements the shouldComponentUpdate inside which shallow equals is used for comparison between previous and next
try following codes:
class MyComponent extends PureComponent {...}

Categories

Resources