How to share state between state between React sibling component functions? [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last year.
Improve this question
How do I use share some state data in one React component function with another? Both are children of yet another component. (I am a React newbie so perhaps somewhat naively I tried: 1) defined an exported const from my ap.jsx with a structure whose properties were the state. Seems like when queried the structure was returning null. 2) cannot use props as that's one way one from parent to child).

I suppose the best answer is: it depends.
However, the most simple solution would be to hold the value in a parent component and pass it down to both child components through props.
If you want to skip few nesting levels, you could reach for React context or state management tools like redux but that is already a heavy tool. Hard to say what exactly is best in your case with context you shared so far.

If you want to share state, you can use Context concept or Redux which is a library for sharing library.
Here is some useful link for you.
https://redux.js.org/
https://reactjs.org/docs/context.html

I agree with akds that the best approach depends on the specific details of your scenario, but that the recommended approach would be to have the parent manage the state, unless the complexity of your scenario dictates otherwise.
Here is a rather trivial example with a component class as the parent to manage the state based on an action taken in the one of the child components, with the two child components being stateless components. The key is that the parent passes down a callback function to the child for whatever event in the child relates to the state change that needs to be handled. In this example, that is just a click on one of the child components, but it could be anything.
Example on CodePen.
Here is the code from the CodePen example:
HTML:
<div id="example"></div>
JS:
import * as React from "https://cdn.skypack.dev/react#17.0.1";
import * as ReactDOM from "https://cdn.skypack.dev/react-dom#17.0.1";
class Parent extends React.Component{
constructor(props){
super(props);
this.state = {child1Selected:false};
}
handleChild1Click(){
this.setState({child1Selected:!this.state.child1Selected});
}
render(){
return (
<div>
<Child1
child1Selected={this.state.child1Selected}
onClick={() => {this.handleChild1Click();}}
style={{width:"100px", height:"100px", backgroundColor:"blue"}}
/>
<Child2
child1Selected={this.state.child1Selected}
style={{width:"100px", height:"100px", backgroundColor:"lightgrey"}}
/>
</div>
);
}
}
function Child1(props){
return (
<div onClick={props.onClick} style={props.style}>
{props.child1Selected ? "I am Selected" : "I am NOT Selected"}
</div>
);
}
function Child2(props){
return (
<div style={props.style}>
{props.child1Selected ? "My Sibling is Selected" : "My Sibling is NOT Selected"}
</div>
);
}
let loadApp = ReactDOM.render(<Parent/>, document.getElementById('example'));
loadApp;

Related

How this.setState() (react.Component method) has access of his child's class state?

Actually, I am learning to React JS, But I have confusion that how can a parent's class method has access to his child's class state. I searched a lot on this topic but in object-oriented programming parent class hasn't access to his child's properties (state). But in react js how setState() has to access to his child's class properties (state). It can be a stupid question please tell me how it happens?
Don't worry, this is a great question.
Props are passed by reference!
Here are some great answers from a StackOverflow post that answer your question with more specificity.
In reactjs, are props pass by value or pass by reference?
I think some potential nuance I can offer is that React emphasizes composition over inheritance. You should think of it as your parent component being composed of the child components. While the child components are given access to the parent state, they aren't inheriting it.
Understanding the Parent Child structure through the Component API may help, should you want to clear any confusion. Since you have mentioned Class Components, let me illustrate an example with the same.
You may send props from a Parent to a child through defining a property within the JSX insertion -
<Child uniqueProp="Text sent to Child" />
Conversely, it is tricky to access Child data in a Parent component. You'll have to follow these steps -
Define a callback function in the Parent Component to get data from the Child Component.
Pass the callback function in the Parent Component as a prop to the Child Component.
The Child Component calls the Parent callback function using props.
Example -
Parent Component
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "Original Text"
}
}
handleCallback = (value) => {
this.setState({ text: value })
}
render() {
return (
<div>
<Child changeText={this.handleCallback} />
{this.state.text}
</div>
)
}
}
Child Component
class Child extends React.Component {
render() {
return (
<div>
<button onClick={() => this.props.changeText("Data from child")}>
Button
</button>
</div>
)
}
}
The reason it is set up that way is because props are passed by reference. Should you choose to change the parent's state traditionally state = {"something"} instead of setState({"something"}), the object will be modified in the child component as well but there will not be a re-render cycle. The user won't see UI changes until a manual refresh.
And when you use setState to change the parent's state (standard practice), the re-render cycle will be triggered as expected and the Child Component will reflect the UI changes.
Note: Be warned, the use of functional components is almost defacto now. Makes life easy with integrations of Hooks and data stores such as Redux in my opinion.

How can saving React Child Components inside state value be efficient?

I'm working on some project where I need to add react child components dynamically. While this task may seem to be easy to complete, I'm concerned about the efficiency of my approach. I surfed the internet and found several solutions that have the same design pattern as mine. Still, I'm doubting myself of efficiency.
Below is my example:
class Container extends Component{
constructor(props){
super(props)
this.state = {
children: []
}
this.addChild = this.addChild.bind(this)
}
addChild(){
this.setState({
children: [...this.state.children,
<div>
<h1> My number is {this.state.children.length} </h1>
</div>]
})
}
render() {
return
<div>
<button onClick={this.addChild}> Add child </button>
{this.state.children.map( child => child)}
</div>
}
}
This example is quite simple. But when you have a complex structure, where components have other components that change state, have events listeners and deep structure, Component's state value will contain a huge amount of code and this component will re-render everything on each addition. On 100th addition, it will make 99 unnecessary re-renders.
Of course, I can use Vanilla JS or JQuery to append new components, but I do not find it to be smart decision. I'd like to keep consistency and solve the problem with React tools.
What are your thoughts? What patterns would you suggest?
Ok, I've just found the answer for this question myself. While React invokes render function on each state change, it does not re-render unnecessary components.
3 years after, I see that this approach is terrible. One should store state values in the array and iterate them in the render function. Not only the code will look more clear, but memory usage will decrease as well.

Triggering a State Change Between Sibling Components

Total React noob here. I have two sibling Components in my React application. I want to display a Loading message in Component A when a certain method is executed in Component B
I'm familiar with passing state from a parent to child in React, but how can a sibling be notified to display it's loader?
Here's what I have so far
export default class ComponentA extends Component {
constructor(props) {
super(props);
this.state = {};
}
render(){
return(
{/* Loader */}
{ this.state.loading === true &&
<div className="loader"></div>
}
)
}
}
export default class ComponentB extends Component {
// Constructor, bindings and stuff...
getData(){
// Update Component A's "loading" state here.
// Once the data is fetched, set "loading" to false
}
render(){
return(
<div>
<button onClick="this.getData"></button>
<table>
<tbody>
{/* ... */}
</tbody>
</table>
</div>
)
}
}
Setting up both Components to inherit state from a Parent Component doesn't seem desirable because I'll have many siblings with nested Components that I'll also want to trigger this loader
Any input is appreciated!
In React, data flows from the top, down. You'd need to wrap Component A and B in a parent and keep the state in the parent as a single point of truth.
However, as you have said after a while this can become tedious when dealing with components several levels deep. You don't want to have to keep passing the state down.
I'd suggest looking into Redux (the docs are excellent) as well as the container(smart)/component(dumb) architecture.
In addition to the links above, I'd really suggest taking the time to watch this free tutorial series from Redux's creator, Dan Abramov.
Hope that helps!
First of all, you said that Component A is a child component of Component B but I don't see any relationship between the two components. But you can do one of 2 things in my opinion. One is to import Component A into Component B as a child component and pass the data to Component A as props (easy). Second way requires you to understand redux. In this case, I don't see the necessity due to the size of the app. However, basically you can have a mastermind at the top of the React component tree to pass down the state to any component. So updating the store by dispatching the new data from Component B will enable Component A to have an access to the data. Redux would be great from large applications and for data that needs to be distributed in multiple places.

Trying to understand data passing in React.js

I want to understand what is being passed from the parent component to the child component properties in the following React.js example (I'm working through this tic-tac-toe tutorial):
class Square extends React.Component {
render() {
return (
<button className="square" onClick={() => this.props.onClick()}>
{this.props.value}
</button>
);
}
}
Then there is a board component that does this to render each square:
renderSquare(i) {
return <Square value={this.state.squares[i]} onClick={() => this.handleClick(i)} />;
}
handleClick(i) {
const squares = this.state.squares.slice();
squares[i] = 'X';
this.setState({squares: squares});
}
squares is an array saved in the state of the board.
The render function of the board is like this:
render() {
const status = 'Next player: X';
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
handleClick updates the squares array that is in Board without seemingly touching Square. This seems a little wonky from my viewpoint of a traditional Java/C++ programmer where I'm looking for something like pass-by-reference vs pass-by-value. The only thing I can guess about what is happening here is that after handleClick is called, the Board's render function is called again and that is how the new square[i] data value is passed to the Square component. So at that point, Square is rendered with a new set of props but the same state it had before. Is that correct?
Even if I'm correct in my understanding, it's what I'm really trying to wrap my head around as a way of thinking about the code I'm going to write. I'm also curious about more details about the control flow of React.js: When should I expect render() for a component to be called again? And does render of a parent call render of all the children it has? I'm curious about if a parent is re-rendered, do all the old child components get destroyed and then a new set is constructed and rendered? If not, how does React.js know which call goes with which Square object?
I'm interested in any advice about how to understand this or articles with good analogies/descriptions about this subject. Even just some jargon about how to describe what is going on here would help me in my own Googling. Thanks, all!
Full example here
Great question! You're asking the right things and I can tell that you're going to have a strong grasp of React within a short time frame. It seems like you could use some help to better understand the component lifecycle and the beauty of one-way data binding. I'll list some resources that you might find help and I'll try my best to answer your specific questions below.
This is a good article on component lifecycles:
http://busypeoples.github.io/post/react-component-lifecycle/
Another great resource/tool is Redux. Not only is it a great tool for debugging but it also helps you learn because it makes it much easier to visualize what is going on behind the scenes.
Redux: https://github.com/reactjs/redux
Questions & Answers:
1) ... curious about more details about the control flow of React.js
When an instance of a component is being created and inserted into the DOM, the following methods are called in this order:
constructor()
componentWillMount()
render()
compnentDidMount()
These methods are called when a component is being re-rendered:
componentWillReceiveProps()
shouldComponentUpdate()
render()
componentDidUpdate()
2) When should I expect render() for a component to be called again?
It's hard to give you a definitive statement as there are a lot of factors that come into play here. Typically, render() gets invoked when you need to load data from a remote endpoint, changes in the values of Props (which could trigger a state change), and changes in state. In other words, when something changes or updates and it requires DOM manipulation, we will likely re-render.
3) Does render of a parent call render of all the children it has?
4) If parent is re-rendered, do all the old child components get destroyed?
3 & 4 here are pretty similar question. When you use setState it is not only the current component that will do a render, but also all nested components. But if a nested component does a setState it will not affect parent components. From my understanding, child components will not get destroyed unless you specify compoentWillUnmount() or by performing clean up operations.
React re-renders a component and its children whenever it is dirty, i.e. its props or state changed.
In your case, by calling setState(), you change the state of your board component and for this reason trigger a rendering of it and all its children.
Note that this does not necessarily mean that all DOM elements are deleted and replaced, as React may reuse them where possible for performance reasons. This process however is abstracted away by the React library for you.

React.js properties

I am currently going through the documentation of React.js and have a question about this.props, which according to the docs should be considered immutable and only pushed downwards down the ownership tree since bubbling custom events upwards is discouraged.
Say that I have a UI where the state of a component in the header of the page should be shared with another component that is nested somewhere in the body of the page, let's take a simple checkbox that represents some specific state that will influence the visibility of some nested spans or divs.
The only I way I currently see this achieved is by creating a state property that is pushed downwards from the top element to the child elements.
The two related questions I have with this is:
Does this mean that I should create one component that owns the entire page? (Is rendering the entire page with a single owner component an acceptable thing to do? I understand the concepts of Virtual DOM and diffing so I assume it's not a problem, still I'd like some confirmation in case I miss out on something relevant);
Is it ok to change the property on this.props when clicking the checkbox, in order to re-render the other components on the page? This doesn't make the props immutable (perhaps they mean just that setting new props on this.props down the chain is not accepted to avoid an untransparent stack trace in case of bugs, but changing the value of a state property is?).
Some confirmation would be appreciated.
Thanks.
1) It is fine to have one parent for the whole page, but is not always necessary. It depends on if it is necessary to share the state between components.
2) You never want to alter props via this.props.someValue = newValue. If you need to modify the parent state from a child component, it should always be done with a callback. The example below shows how to share the checkbox state between multiple components using the callback function handleClick to modify the state of is_checked.
JSFiddle of example: https://jsfiddle.net/mark1z/o7noph4y/
var Parent = React.createClass({
getInitialState: function(){
return ({is_checked: 0})
},
handleClick: function(){
this.setState({is_checked: !this.state.is_checked})
},
render: function(){
return (
<div>
<CheckBox is_checked={this.state.is_checked} handleClick={this.handleClick}/>
<OtherComponent is_checked={this.state.is_checked} />
</div>
);
}
});
var CheckBox = React.createClass({
render: function() {
return (
<input type="checkbox" onChange={this.props.handleClick}> Show other component </input>
);
}
});
var OtherComponent = React.createClass({
render: function() {
return (
<div style={{marginTop: 20}}>
{this.props.is_checked ? 'The checkbox is ticked' : 'The checkbox is not ticked'}
</div>
);
}
});
React.render(<Parent />, document.getElementById('container'));
I guess having one master component isn't an issue. The docs suggest that you find the topmost component that can supply it's children with the needed data - and this could easily be the toplevel master component. As I understand this you would have a master component for your main page - that should be the only one that uses state, the children just render what they are given in props. So no, props should not be altered by a child that doesn't own the data, it is the topmost components prerogative to do so. Let's say you have another widget on the page that only cares for a distinct set of data you would make this the root of another tree that fetches data and sets it's state and the props of it's children.
Here is a crappy graph for this situation:
App -(props)-> ItemList -(props)-> Item -(props)-> Photo
+ + |
+ ++++++++++ |----(props)-> LikeButton
+ + |
(fetch) + |
+ + * ---(props)-> Description
++(setState)++
Widget -(props)-> Whether
However it gets more interesting when facebook's graphql is finalized and every component can declare the needed data on it's own, I'm looking forward to it. But until then the toplevel component has to know which data every child needs and all the parent nodes need to hand this data down.

Categories