How can I update the state of a child component from the parent component in ReactJS? - javascript

I've tried passing a function as a prop to the child component, but I'm not sure how to call it from the parent component.
// Parent Component
function Parent() {
const [childState, setChildState] = useState(false);
const handleClick = () => {
// How can I update the state of the child component from here?
};
return ( <div> <Child childState={childState} setChildState={setChildState} /> <button onClick={handleClick}>Update Child State</button> </div> );
}
// Child Component
function Child({ childState, setChildState }) {
return ( <div> <p>Child State: {childState.toString()}</p> </div> );
}

in your example you do not need to pass "childState, setChildState" in to the child function as it already has access to them.
Something like this should work for you
function Parent() {
const [childState, setChildState] = useState(false);
// We have access to childState here
function Child() {
return ( <div> <p>Child State: {childState.toString()}</p> </div>
); }
// Updating state
const handleClick = () => {
setChildState(!childState)
};
return ( <div>
<Child childState={childState} setChildState={setChildState} />
<button onClick={handleClick}>Update Child State</button> </div>
);
}

Related

pass an array from a child to parent ReactJS

i have an array in a component i want to export it or pass it to other component (parent)
child component :
export default function child(){
const arr = ["1020","52214","3325"]
return (
<div> child</div>
)
}
parent :
export default function parent(){
return (
<>
<div> parent</div>
<child/>
</>
)
}
In react we don't pass values from child to parent but the other way around: it's a one-way data flow!
You can useState to create a stateful value and a set-function in the parent, pass the set function to the child and allow it to set the value.
Example:
export default function child(props){
const arr = ["1020","52214","3325"];
props.setMyArray(arr);
return (
<div> child</div>
)
}
import { useState } from 'react';
export default function parent(){
const [myArray, setArray] = useState([]);
return (
<>
<div> parent</div>
<child setMyArray={setArray}/>
</>
)
}
}
You can't pass data from child to parent.
You can pass like this.
const ParentPage = () => {
const [arr , setArr ] = useState([])
console.log(arr) // [1,2,3]
return (
<ChildPage setArr={setArr} />
);
}
const ChildPage = ({setArr}) => {
return (
<button onClick={()=> setArr([1,2,3]) }}> </button>
);
}
or you can do with redux
You can use props to call a function in the parent element and pass an argument in the function from the child element.
Here's an example:
Child element:
export default function child(props){
const [arr,setarr]= useState(["1020","52214","3325"]);
return (
<div onclick={()=>{props.func(arr)}}> child</div>
)
}
Parent element:
export default function parent(){
function passvalue(arr){
const passedvalue = arr;
}
return (
<>
<div> parent</div>
<child func={passvalue}/>
</>
)
}

React JS pass the data or child component to parent component

Is it possible to pass the data from the child component to the parent component using props?
-Parent component
--- ItemList component.
--- DisplatSelect component from the itemList component
I have a list of item in the child component which came from to the parent component, then I want to send the index of the selected data to the other child component located in the parent component.
Can't example well, kindly see the attached screenshot for other references.
Thanks a lot!
enter image description here
You can keep the data in the Parent component and use a function to pass the props from the child to the Parent. This concept is called Lifting State Up where you define the state at the highest common ancestor so all the child components are using the same data which in this case is the selecetd item
function Parent() {
const [selectedItem, setSelectedItem] = useState(null);
const data = []; // Your Data
return (
<>
<h1>Your selected Item = {selectedItem}</h1>
{data.map((item) => {
<Child item={item} setSelectedItem={setSelectedItem} />;
})}
</>
);
}
function Child({ item, setSelectedItem }) {
return <Button onClick={() => setSelectedItem(item.id)}> {item} </Button>;
}
The simplest way, I think, is for the child component where the selection is made to accept a function properly, something like onSelectionChanged. If you had a button for each item passed to the child you could do something like:
Child Component A
const ChildA = ({ items, onSelectionChanged }) => {
return (
<div>
{items.map((item, index) => (
<button onClick={() => onSelectionChanged(index)}>Item</button>
))}
</div>
)
}
Child Component B
const ChildB = ({ selectedItem }) => {
return (
<div>
Selected {selectedItem}
</div>
)
}
Parent Component
const Parent = () => {
const [selection, sets election] = useState({});
const onSelectionChanged = index => {
console.log(`ChildA selection changed: ${index}`);
}
return (
<div>
<ChildA items={items} onSelectionChanged={onSelectionChanged} />
<ChildB selectedItem={selection} />
</div>
)
}
So when your child component handles a change in the selection, it invokes the function passed as a prop onSelectionChanged. You can pass whatever data you want from ChildA to that function.
Note that the parent Component keeps the selected value (from ChildA) in local state, then passes that value to ChildB via a prop.
You can have a state variable in the parent component and pass it to child components to share data between them. I'll post a sample code block on how you can do this for your case.
export default function ParentComponent (props) {
const data = ['image_1_url', 'image_2_url', ...] // Data for the images
const [selectedIndex, setSelectedIndex] = useState(-1); // Selected index (-1 represents no selection)
return (
<ImageList data={data} selectImage={setSelectedIndex} />
{(selectedIndex !== -1) ? (<SelectedImage data={data[selectedIndex]} />) : (<No ImageSelected/>)}
);
}
And the image list component can then use the selectImage prop to select the image
export default function ImageList (props) {
return (
<div>
props.data.map((imageUrl, index) => (
<div onClick={() => {props.setSelected(index)}}>
<img src={imageUrl}/>
</div>
))
</div>
);
}
Yes it's possible. We have one parent state value and update every on click child component to the component.
import React, { useState } from "react";
const Child1 = (props) => {
return (
props.items.map( (item, index) => (
<button key={index.toString()} onClick={() => { props.updateIndex(item.id) }}>
{item.name}
</button>
) )
)
}
const Child2 = (props) => {
return (
<h1>Item selected: {props.selectItem}</h1>
)
}
const ParentComponent = () => {
const listItems = [
{
id:1,
name: "sample name 1"
},
{
id:2,
name: "sample name 2"
}
]
const [selectItem, setSelectItem] = useState('None');
return (
<>
<Child1 items={listItems} updateIndex={setSelectItem}/>
<Child2 selectItem={selectItem}/>
</>
)
}
export default function App() {
return (
<div className="App">
<ParentComponent/>
</div>
);
}

Is it possible to add ref to the props.children elements?

I have a Form and Input components, which are rendered as below.
<Form>
<Field />
<Field />
<Field />
</Form>
Form component will act as wrapper component here and Field component ref are not being set here. I want iterate through props.children in Form Component and want to assign a ref attribute to each children. Is there any possibility to achieve this?
You need Form to inject your refs with React.Children and React.cloneElement APIs:
const FunctionComponentForward = React.forwardRef((props, ref) => (
<div ref={ref}>Function Component Forward</div>
));
const Form = ({ children }) => {
const childrenRef = useRef([]);
useEffect(() => {
console.log("Form Children", childrenRef.current);
}, []);
return (
<>
{React.Children.map(children, (child, index) =>
React.cloneElement(child, {
ref: (ref) => (childrenRef.current[index] = ref)
})
)}
</>
);
};
const App = () => {
return (
<Form>
<div>Hello</div>
<FunctionComponentForward />
</Form>
);
};
You can map children create new instance of component based on it using one of two ways showed in React Docs.
With React.Children.map and React.cloneElement (this way, key and ref from original element are preserved)
Or only with React.Children.map (Only ref from original component is preserved)
function useRefs() {
const refs = useRef({});
const register = useCallback((refName) => ref => {
refs.current[refName] = ref;
}, []);
return [refs, register];
}
function WithoutCloneComponent({children, ...props}) {
const [refs, register] = useRefs();
return (
<Parent>
{React.Children.map((Child, index) => (
<Child.type
{...Child.props}
ref={register(`${field-${index}}`)}
/>
)}
</Parent>
)
}
function WithCloneComponent({children, ...props}) {
const [refs, register] = useRefs();
return (
<Parent>
{
React.Children.map((child, index) => React.cloneElement(
child,
{ ...child.props, ref: register(`field-${index}`) }
)
}
</Parent>
)
}

How to access properties in child from children props in react

The title is pretty straightforward, I need to access a property (a ref to be precise) on a child element that is passed through the children of my component, which means that I can't pass the ref in the parent afaik.
Here's a minimal example to highlight my issue:
import React from "react";
class Child extends React.Component {
myRef = React.createRef();
render() {
return <div ref={this.myRef}>child</div>;
}
}
const Parent = ({ children }) => {
const myChild = React.Children.toArray(children).find(
child => child.type === Child
);
// I want to access this
console.log(myChild.myRef);
// but it's undefined
return (
<div>
<h1>Parent</h1>
{children}
</div>
);
};
// I can't really change this component
export default function App() {
return (
<div className="App">
<Parent>
<Child />
</Parent>
</div>
);
}
I made a codesandbox highlighting my issue https://codesandbox.io/s/eloquent-wing-e0ejh?file=/src/App.js
Rather than declaring ref in <Child/>, you should declare ref in your <Parent/> and pass it to the child.
import React from "react";
class Child extends React.Component {
render() {
return <div ref={this.props.myRef}>child</div>;
}
}
const Parent = ({ children }) => {
const myRef = React.useRef(null);
// access it from here or do other thing
console.log(myRef);
return (
<div>
<h1>Parent</h1>
{ children(myRef) }
</div>
);
};
export default function App() {
return (
<div className="App">
<Parent>
{myRef => (
<Child myRef={myRef} />
)}
</Parent>
</div>
);
}

Ref from Dropdown.Button (antd)

How can I get a ref to a Dropdown.Button (it is antd), when I set a ref to it, it returns a wrapper ?
parent = null;
parentRef = node => (this.parent = node);
render(){
return (
<Dropdown.Button
ref={this.parentRef}
overlay={menu}
type="primary"
>
content
</Dropdown.Button>
)
}
You need to use reference API, useRef or React.createRef.
Refer to Refs and the DOM in React:
class App extends React.Component {
buttonRef = React.createRef();
componentDidMount() {
console.log(this.buttonRef);
}
render() {
return (
<Dropdown.Button ref={this.buttonRef} overlay={menu} type="primary">
content
</Dropdown.Button>
);
}
}
With hooks:
const App = () => {
const buttonRef = useRef();
useEffect(() => {
console.log(buttonRef);
}, []);
return (
<FlexBox>
<Dropdown.Button ref={buttonRef} menu={menu}>
drop down
</Dropdown.Button>
</FlexBox>
);
};
Hei,
Check out the React.forwardRef() here.
It's a function which you can wrap your 'child' component and it's specifically designed to make possible parent to have a reference to its children. Should solve your problem.
Cheers!
you can by passing a cb function on the ref attrib:
parent = null;
parentRef = ref => (this.parent = ref);
render(){
return (
<Dropdown.Button
ref={parentRef}
overlay={menu}
type="primary"
>
content
</Dropdown.Button>
)
}
Or with useRef hook:
for functional components no classes
const parentRef =React.useRef(null);
return (
<Dropdown.Button
ref={parentRef}
overlay={menu}
type="primary"
>
content
</Dropdown.Button>
)

Categories

Resources