Access all children component of a React component - javascript

I have react component A which renders a table. Data for one of the columns in the table is rendered through another component B, so <B/> is child of <A/>. I want to perform some action on <B/> whenever user clicks anywhere on the page. This click event listener is defined inside A. How can I loop through all <B/>s from inside class A? My component structure is something like this:
class A extends React.Component {
<B/>
<B/>
<B/>
<B/>
};
I came across React.Children.forEach, but that is useful when children are passed as props via this.props.children; i.e. when the code is something like this:
<A>some markup</A>

const childrenProps = React.Children.map(this.props.children,
(child) => React.cloneElement(child, {
data : this.state,
method : this.method.bind(this)
// here you can pass state or method of parent component to child components
}));
// to access you can use this.props.data or this.props.method in child component
you need to pass this {childrenProps} which include all child components.

So I figured it out. I gave ref to each <B/>, and stored it in an array:
class A extends React.Component {
collectRefs = [];
<B ref={b => {this.collectRefs.push(b)}}/>
<B ref={b => {this.collectRefs.push(b)}}/>
<B ref={b => {this.collectRefs.push(b)}}/>
for(const b of collectRefs) {
// do stuff
}
}

Related

React cannot update during an existing state transition (such as within render ) functional component

I am dealing with two components and one store.Components are Child and Parent,Store is store. Parent when rendering, make the child component up and parent listens to store.Now I want to update the state of variable in Store, by exposing a method from Store. The parent pass this method as a call back to child. Child has a dialog box, and if user closes/dismiss that dialog box, the clearStoreInfo() should be called, which is passed by parent to child. But when i do so, I get error
React cannot update during an existing state transition (such as within render ) functional component
Store looks as :
class Stores {
........
........
........
#action.bound
clearStoreInfo = () => {
console.log(" clear info");
}
}
Parent Component:
import Store ........
class InfoContainer extends React.Component {
return (
<div id={"info"} className={"container"}>
<ButtonPanel store={Store} />
</div>
}
const ButtonPanel = (props) => {
return (
.....
.....
<div>
<ChildComponent clearStoreInfo={props.store.clearStoreInfo}/>
</div>
......
}
class ChildComponent extends React.Component {
render(){
const {clearStoreInfo} = this.props;
return (
////if -else ladder
clearStoreInfo(); // warning line.
<Dialog.......
onClose={clearStoreInfo}
/>
)
}
//Because of warning, the dialog box dont come. If i remove clearStoreInfo(), then dialog box works fine.
Is there any easy workaround given these components and store?
The wiring works fine, because I can see console log,based on if-else ladder, but its just the warning is messing things up internally.onClose is able to call the clearStoreInfo perfectally, but its when I manually call it, I am getting a warning.

How to access a function in a child class component from a stateless parent?

I have a redux-store with objects of initial values. And this store will get updated at a few places within the child component.
I created a stateless functional component as parent
const Parent = () => {
const store = useSelector(state => state);
const getInitState = () => {
depends on store, it will return an object as initial state for child component
}
let initState = getInitState(); //it has to be let instead of const, it could be changed during useEffect
useEffect(() => {
some initialization on mount
}, [])
return ( // return is simplified here
<Child initState={iniState} />
)
}
export default Parent;
I have a class child component something like below
class Child extends Component {
state = {
componentState: this.props.initState
}
....
}
export default Child;
I can't modify the child component It's a very complex component with many sub components which I dont handle.
Now I need to access setState function of child component from parent. Or I need to change the state of child from parent, is there a way to do that?
Yes, I understand a new design should be consider since it's anti-pattern, but I am just wondering if I can do it under current setting.
Thank you all in advance.
==============================================================
Edit: For whoever runs into the same problem, functional component does not support constructor. So I have included a breif correction to the answer.
Define parent as below
import React, { useRef } from "react";
const Parent = () => {
const childRef = useRef(null);
return (
<Child ref={childRef} />
)
}
export default Parent;
Then you are able to use childRef.current to access all function from child component.
The best way is using a react Context , and set state in parent then the child consume state of parent (using react hooks would be so easy than class component)
but in your case as you mentiened (I wonder I can do it under current setting)
you can use react refs :
first put ref prop in your rendered component tag then use it in parent to execute function that's declared inside child
as below :
inside parent component :
const Parent = () => {
.
.
.
constructor() {
//create react ref for our component
this.childComponent = React.createRef();
}
callChildFunction() {
// here using refs you can access function in you child refenrenced component
this.childComponent.cuurent.doSomeUpdateStateStuff(newState);
}
return ( // return is simplified here
<Child ref={this.childComponen} initState={iniState} />
)
...
}
and your child :
class Child extends Component {
state = {
componentState: this.props.initState
}
doSomeUpdateStateStuff(state) {
// stuff updating state callled from parent
}
....
}

Accesing the state of child component

I have a parent component which contains a function, which when called needs to acces the childrenĀ“s component state. I dont want to move the whole state to the parent component because i want the children component to be independent. What is the cleanest and most recommended way to achieve this?
class ParentComponent extends Component {
render() {
return (
<div>
<ChildComponent/>
<SaveButton onClick={this.saveFunction}/>
</div>
)
}
saveFunction = () => {
//Here i need to acces the child Component state
}
}
My solution so far was that everytime something changed in child component i called a function which was passed from the parent Component. Like this:
class ChildrenComponent extends Component {
state = {
name: "David",
age: 19
}
render() {
return (
//inputs with the inputChange function
)
}
inputChange = (e) => {
//Update the state
//Then pass the state to the parent
this.props.passStateToParent(this.state)
}
}
I would recommend to look up some of the React patterns - especially Render Props, as it allows to expose the state and wanted methods of a component - what you want in this situation.
Best of luck!
You can make a function in parent component and pass it down to child component as prop. This function could return to parent component the state of your child component. See more here: https://reactjs.org/docs/faq-functions.html
You cannot directly access the state of the child component,this can be done by passing the state to methods of parent component which are passed as props to child component,the following example demonstrate how to do it .
class ParentComponent extends React.Component {
somefunc() {
//do your action
}
render() {
<ChildComponent parentfunc={this.somefunc}/>
}
}
class ChildComponent extends React.Component {
constructor(props){
super(props)
this.state = {somedate:'value'}
this.func = this.func.bind(this)
}
func() {
this.props.parentfunc(this.state)
}
render() {
<button onClick={this.func}>text</button>
}
}

How to pass state back to parent in React?

I have a form that has a submit button.
That form calls a function onclick that sets the state of something from false to true.
I then want to pass this state back to the parent so that if it is true it renders componentA but if it is false it renders componentB.
How would I do that in react?
I know I need to use state or props but not sure how to do it. also is this contradicting the one-way flow react principle??
ComponentA code:
<form onSubmit={this.handleClick}>
handleClick(event) {
this.setState({ decisionPage: true });
event.preventDefault();
};
Parent component that controls what it displays:
return (
<div>
{this.props.decisionPage ?
<div>
<LoginPage />
</div>
:
<div>
<Decision showThanks={this.props.showThanks}/>
</div>
}
</div>
)
Move handleClick to the parent and pass it to the child component as a prop.
<LoginPage handleClick={this.handleClick.bind(this)}/>
Now in the child component:
<form onSubmit={this.props.handleClick}>
This way submitting the form will update the state in parent component directly. This assumes you don't need to access updated state value in child component. If you do, then you can pass the state value back from the parent to the child as a prop. One-way data flow is maintained.
<LoginPage handleClick={this.handleClick.bind(this)} decisionPage={this.state.decisionPage}/>
Pass State as a Prop
I have recently learned a method that works great for changing state in a <Parent /> component from a <Child /> component.
This might not be the exact answer for this question, but it is surely applicable to this situation and other similar situations.
It works like this:
set the default STATE in the <Parent /> component - Then add the 'setState' attribute to the <Child />
const Parent = () => {
const [value, setValue] = useState(" Default Value ");
return (
<Child setValue={setValue} />
)
}
Then change the state(in Parent) from the Child component
const Child = props => {
return (
<button onClick={() => props.setValue(" My NEW Value ")}>
Click to change the state
</button>
)
}
When you click the button, the state in the <Parent /> component will change to whatever you set the state to in the <Child /> component, making use of "props".. This can be anything you want.
I Hope this helps you and other devs in the future.
In Parent Component:
getDatafromChild(val){
console.log(val);
}
render(){
return(<Child sendData={this.getDatafromChild}/>);
}
In Child Component:
callBackMethod(){
this.props.sendData(value);
}
Simple Steps:
Create a component called Parent.
In Parent Component create a method that accepts some data and sets
the accepted data as the parent's state.
Create a component called Child.
Pass the method created in Parent to child as props.
Accept the props in parent using this.props followed by method
name and pass child's state to it as argument.
The method will replace the parent's state with the child's state.
Here is an example of how we can pass data from child to parent (I had the same issue and use come out with this )
On parent, I have a function (which I will call from a child with some data for it)
handleEdit(event, id){ //Fuction
event.preventDefault();
this.setState({ displayModal: true , responseMessage:'', resId:id, mode:'edit'});
}
dishData = <DishListHtml list={products} onDelete={this.handleDelete} onEdit={(event, id) => this.handleEdit(event, id)}/>;
At the child component :
<div to="#editItemDetails" data-toggle="modal" onClick={(event)=>this.props.onEdit(event, listElement.id) }
className="btn btn-success">
In React you can pass data from parent to child using props. But you need a different mechanism to pass data from child to parent.
Another method to do this is to create a callback method. You pass the callback method to the child when it's created.
class Parent extends React.Component {
myCallback = (dataFromChild) => {
//use dataFromChild
},
render() {
return (
<div>
<ComponentA callbackFromParent={this.myCallback}/>
</div>
);
}
}
You pass the decisionPage value from the child to the parent via the callback method the parent passed.
class ComponentA extends React.Component{
someFn = () => {
this.props.callbackFromParent(decisionPage);
},
render() {
[...]
}
};
SomeFn could be your handleClick method.
if your parent component is a functional component you can now use the use context way. Which involves passing the ref to the object and the ref to the stateChanging method. What this will allow you to do is change state from parrent in child and also ref tht state while remaining synced with Parent State. You can learn more about this in a youtubeVideo by codedamn titled 'React 16.12 Tutorial 20: Intro to Context API' and 'React 16.12 Tutorial 21: useContext'
This works exactly what I wanted. But in case of set of data with say 50 records with (customer_id, customer_name) as values to be updated from child to parent, then this lags. Do the setState using React.useEffect in child component
i have same problem and so performed this code :
in Parent
const PARENT = () => {
const [value, setValue] = useState("....");
return (
)
}
in Child
const CHILD = props => {
return (
<button onClick={() => props.setValue("....")}>
Click to change the state
</button>
)
}

react loop update state

I'm new to react and what I'm doing is loop to get to show the each element form the props and I want form the picture component update that props, I try to find a way to do it but I didn't know how to do it.
Code for the loop is this:
const pictureItems = this.props.imgFiles.map((img, index) => {
return <picture key={index} imgFile={img} pictureDataUpdate={this.onUpdatPicture} />;
});
The question is how can I update the props that are been pass to the picture component? (I'm already passing the information from picture to the component that is looping). I have so far this.
onUpdatPicture(data) {
console.log(data);
// this.setState(data);
}
The simplest method for manipulating props sent to a child component would be to store the data in the parent component's state. Doing so would allow you to manipulate the data and send the updated version to your child component.
Assuming our parent component is sent an array of image urls as the images prop, we'll need two main pieces in our code: our update function for our child to call and to map over our images and create our children.
class Gallery extends React.Component {
constructor(props) {
super(props)
//Setting our props to the state of the parent allows us to manipulate the data before sending it back to our child.
this.state = {
images: this.props.images || []
}
}
update = (key, value) => {
// Our update function is sent the {key} of our image to update, and the new {value} we want this key to hold.
// After we are passed our data, we can simply map over our array and return the new array to our state.
this.setState({
images: this.state.images.map( (img, i) => i === key ? value : img)
})
};
render() {
return (
<div className="gallery"> // Since we are going to have multiple children, we need to have a wrapper div so we don't get errors.
{
// We map over our data and send our child the needed props.
// We send our child the {src} of our image, our {update} function, the id our child will use to update our parent, and a key for React to keep track of our child components
images.map( (img, i) => <Picture src={img} update={this.update} id={i} key={'picture_' + i} />)
}
</div>
)
}
}
After we have our update function setup and our parent is mapping over our images to create the child component, all that's left to do is setup our child component to handle our data.
class Picture extends React.Component {
render() {
return (
// Notice our onClick is an arrow function that calls our update method. This is so we only call our update function once the onClick is fired, not when the component is being rendered.
<div className="picture" onClick={() => this.props.update(this.props.id, 'https://static.pexels.com/photos/189463/pexels-photo-189463.png')}>
<img src={this.props.src} />
</div>
)
}
}
Given the above code, once we render our gallery component, anytime an image is clicked, the child's image is replaced with a new image.
Here is a link to a working example on CodePen.

Categories