In reactjs, I want to get child component value at parent. Here is my code for parent and child.
child.js
import React, {useState, useEffect} from 'react';
export const Child = () => {
const [state, setState] = useState({name: ""});
const handleInputTextChange=(e)=> {
const {name,value}=e.target;
let newState = {...state};
newState.name = name;
setState(newState);
}
return(
<div key="c-div" className="child">
<input required id="child" name="childname" value={state.name} onChange={(e)=>handleInputTextChange(e)}/>
</div>
);
}
parent.js
import React, {useState} from 'react';
import {Child} from './child.js';
export const Parent = () => {
const [names, setnames] = useState([]);
const handleSubmit = async (e) => {
e.preventDefault();
const newNames = [...names];
newNames[0] = '1st';
newNames[1] = '2nd';
setnames(newNames);
}
return(
<div key="div1">
<form name="myformname" id="myformid" onSubmit={handleSubmit}>
<Child />
<Child />
<button> Print Child Names </button>
</form>
The first child names are <b>{names[0]}</b> and <b>{names[1]}</b>
</div>
);
}
I am finding multiple issues in it.
If I type in textfield of child, its not showing, its showing always childname as value.
My main question in such cases, how can I get the value from child at parent.
I will be more interested to know if I can get value like child1.getName(), child2.getName() kind of function so that I will not have to make use of callbacks or state variable in parent.
One way to pass data from a child to a parent component is to define a callback function in the parent component and pass it down to the child component as a prop. The child component can then call this function with the data it wants to pass up to the parent.
Parent.js
import React, { useState } from 'react';
import { Child } from './Child';
export const Parent = () => {
const [names, setNames] = useState(['', '']);
const handleChildNameChange = (updatedState, index) => {
const newNames = [...names];
newNames[index] = updatedState.name;
setNames(newNames);
};
const handleSubmit = async (e) => {
e.preventDefault();
// This part remains the same as you provided
const newNames = [...names];
newNames[0] = '1st';
newNames[1] = '2nd';
setNames(newNames);
};
return (
<div key="div1">
<form name="myformname" id="myformid" onSubmit={handleSubmit}>
{/* Pass props to each Child */}
<Child onNameChange={(updatedState) =>
handleChildNameChange(updatedState, 0)} />
<Child onNameChange={(updatedState) =>
handleChildNameChange(updatedState, 1)} />
<button>Print Child Names</button>
</form>
The first child name is <b>{names[0]}</b> and the second child name is
<b>{names[1]}</b>
</div>
);
};
Child.js
import React, { useState } from 'react';
export const Child = ({ onNameChange }) => {
const [state, setState] = useState({ name: '' });
const handleInputTextChange = (e) => {
const { name, value } = e.target;
let newState = { ...state };
newState[name] = value; // Use name as key to update state dynamically
setState(newState);
onNameChange(newState); // Call callback with updated state
};
return (
<div key="c-div" className="child">
<input
required
id="child"
name="name" // Fixed the name attribute to "name"
value={state.name}
onChange={(e) => handleInputTextChange(e)}
/>
</div>
);
};
Explanation:
Child Component (Child.js):
Added a name attribute to the field to correctly capture its value in the handleInputTextChange function.
Modified handleInputTextChange to update state[name] dynamically based on the name attribute of the input field.
Added a call to onNameChange(newState) to invoke the callback provided by the parent whenever the input changes.
Parent Component (Parent.js):
Introduced names state to store the names entered in both Child components.
Created handleChildNameChange function to update the names state array based on the index of the child component that is updated.
Passed onNameChange callback to each Child component, which calls handleChildNameChange with the updated state and index.
This structure ensures that each Child component can independently update the Parent component’s state (names) when the input value changes, and the parent component manages the overall state of names. Now, when you submit the form or interact with the components, the parent component will have access to the names entered in each child component.
You can not access child component directly from the parent one. For basic use, You can try with forwardRef
, which pass ref of child component to parent.
reference for forwardRef
For complex logic, We use context api or any other global state management library.
You can either use Redux, Recoil or Atom for such task (if you need to use the same variables on multiple other pages)
** OR **
You could declare the state variables on the parent component and use it as props in the child component.
import React, {useState, useEffect} from 'react';
export const Child = ({names, setnames}) => {
const [name, setName] = useState('');
const handleInputTextChange=(e)=> {
setName(e.target.value);
}
const setTheName = () => {
const temp = names;
temp.push(name);
setNames(temp);
}
return(
<div key="c-div" className="child">
<input required id="child" name="childname" value={state.name} onChange={(e)=>handleInputTextChange(e)}/>
<button onClick={e => setTheName()}>set name</button>
</div>
);
}
import React, {useState} from 'react';
import {Child} from './child.js';
export const Parent = () => {
const [names, setnames] = useState([]);
const handleSubmit = async (e) => {
e.preventDefault();
//handle logic
//the names are already assigned to the 'names' variable
}
return(
<div key="div1">
<form name="myformname" id="myformid" onSubmit={handleSubmit}>
<Child names={names} setnames={setnames}/>
<Child names={names} setnames={setnames}/>
<button> Print Child Names </button>
</form>
The first child names are <b>{names[0]}</b> and <b>{names[1]}</b>
</div>
);
}
If you are working on a large project I would recommend using Redux or some similar library for maintaining states.