React - Passing data counter from child to parents component - reactjs

so, im just learning about props method and i want to try how to passing data from child to parent component.
im trying to make counter app, when click + the counter increasing and click - the counter decreasing
i have parent component like this
import React, { useState } from 'react';
import ComponentB from './ComponentB'
const ComponentA = () => {
const [counterB , setCounterB] = useState(0);
return(
<div>
<h1>ComponentB</h1>
<h3>{counterB}</h3>
<ComponentB
add={counterB => setCounterB(counterB)}
subtract={counterB => setCounterB(counterB)}/>
</div> );
}
export default ComponentA;
and child component like this
import React from 'react';
const ComponentB = (props) =>{
return(
<div>
<button onClick={()=> props.add(+1)}>+</button>
<button onClick={()=> props.subtract(-1)}>-</button>
</div>
);
}
export default ComponentB

With
return(
<div>
<h1>ComponentA</h1>
<h3>{counterB}</h3>
<ComponentB
add={diff => setCounterB(counterB + diff)}
subtract={diff => setCounterB(counterB + diff)}/>
</div> );
you pass the function diff => setCounterB(counterB + diff) to ComponentB as prop.add. This function sets the state of counterB to the first argument of that function. So when the button invokes props.add(+1)} the value of counterB is set to 1 every time it is pressed.
What you want is to add +1 to the state of counterB. Thus you should it this way:
// Get a hook function - only needed for this Stack Snippet
const {useState} = React;
const ComponentA = () => {
const [counterB , setCounterB] = useState(0);
return(
<div>
<h1>ComponentA</h1>
<h3>{counterB}</h3>
<ComponentB
add={diff => setCounterB(counterB + diff)}
subtract={diff => setCounterB(counterB + diff)}/>
</div> );
}
const ComponentB = (props) =>{
return(
<div>
<button onClick={()=> props.add(+1)}>+</button>
<button onClick={()=> props.subtract(-1)}>-</button>
</div>
);
}
ReactDOM.render(
<ComponentA/>,
document.getElementById("react")
);
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

I'd suggest to create a method in the Parent component to update the state given a value received from the child.
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.updateCountWithValue = this.updateCountWithValue.bind(this);
}
updateCountWithValue(value) {
let count = this.state.count;
count += value;
this.setState({
count: count
});
}
render() {
return (
<div>
<h1>{`Count: ${this.state.count}`}</h1>
<Child updateCount={this.updateCountWithValue} value={1} />
<Child updateCount={this.updateCountWithValue} value={-1} />
</div>
);
}
}
class Child extends Component {
render() {
return (
<div>
<button onClick={() => this.props.updateCount(this.props.value)}>
{this.props.value}
</button>
</div>
);
}
}
As you can see, the props of my Child component are:
The value that the child will update or change
A method to update the Parent component.
I made this sample so you can see how it works: https://codesandbox.io/s/child-to-parent-uvfmi?file=/src/App.js

Instead of this:
<ComponentB
add={counterB => setCounterB(counterB)}
subtract={counterB => setCounterB(counterB)}/>
Try this:
<ComponentB
add={val => setCounterB(counterB+val)}
subtract={val => setCounterB(counterB+val)}/> // using '+' coz val = -1

Related

How to set state in parent from one child component and access the state in another child component using react and typescript?

i want to set the state in Parent component on clicking a button in child component. Also i want to access this state in other child component.
what i am trying to do?
On clicking upload button (UploadButton component) i want the state isDialogOpen to be set to true. and i want to access isDialogOpen state in UserButton component.
below is the snippet,
function Main() {
return (
<Wrapper>
<React.Suspense fallback={null}>
<Switch>
<Route
exact
path="/page1"
render={routeProps => (
<Layout>
<React.Suspense fallback={<PlaceHolder></>}>
<child1 {...routeProps} />
</React.Suspense>
</Layout>
)}
/>
<Route
exact
path="/page2"
render={routeProps => (
<Layout>
<Child2 {...routeProps} />
</Layout>
)}
/>
</Switch>
</React>
</Wrapper>
)
}
function Child1() {
return (
<UploadButton/>
);
}
type Props = RouteComponentProps<{ itemId: string; productId: string }>;
function UploadButton({ match }: Props) { //here i set the state isDialogOpen
const [isDialogOpen, setDialogOpen] = React.useState(false);
const handle_click = () => {
setDialogOpen(!isDialogOpen);
};
return (
<>
<Button onClick={handle_click}/>
{isDialogOpen && (
<UploadForm/>
)}
</>
);
}
function Child2() {
return (
<UserButton/>
);
}
function UserButton() {
return (
<Icon/>
);
}
In the above snippet, isDialogOpen state is set in UploadButton component.
Now i want to modify above snippet such that the Icon component in UserButton component is hidden if isDialogOpen is true.
i want to access this isDialogOpen state in UserButton component.
what i have tried?
I can define a function in main component that sets isDialogOpen to true when Upload button is clicked in UploadButton component. but this needs passing the function as prop from main component to Upload Button and similarly passing the state to UserButton from main component.
Is there some neat way to do this? i am new to typescript and react. could someone help me solve this. thanks.
You should define state value and function which update state as props respectively to child components as props. You can take example of the code which I provide bellow
const Child1 = (props) => {
return <div>This is the counter value {props.counter}</div>
}
const Child2 = (props) => {
return <div>
<h2>Here the button to update the counter</h2>
<button onClick={props.update}>
Update counter state in the parent
</button>
</div>
}
class MainComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
counter: 0
}
}
updateCounter = () => {
this.setState({counter: this.state.counter + 1});
}
render() {
return <div>
<Child1 counter={this.state.counter} />
<Child2 update={this.updateCounter} />
</div>
}
}
ReactDOM.render(<MainComponent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You can use the same component with context API and React HOOKS like this
import React, { useContext, useState} from 'react';
const CounterContext = React.createContext({
counter: 0
});
const MainComponent = (props) => {
const [counter, setCounter] = useState(0);
const updateCounter = () => {
setCounter(counter + 1);
}
return <CounterContext.Provider value={
counter,
update: updateCounter
}>
<div>
<Child1 />
<Child2 />
</div>
</CounterContext.Provider>;
}
const Child1 = (props) => {
const counter = useContext(CounterContext);
return <div>This is the counter value {counter.counter}</div>
}
const Child2 = (props) => {
const counter = useContext(CounterContext);
return <div>
<h2>Here the button to update the counter</h2>
<button onClick={counter.update}>
Update counter state in the parent
</button>
</div>
}

How to pass the data from child to parent? when parent is class based and child is functional based

I want to pass the data which is anything like, array, strings, numbers into the App(Parent) Component) from the Child1(Child) components.
There's a parent who is class-based and the child is functional based.
Parent:
import React, { Component } from "react";
import "./App.css";
import Child1 from "./Child1/Child1";
class App extends Component {
state = { message: "" };
callbackFunction = (event) => {
this.setState({
message: event.target.value
});
}
render() {
return (
<div className="App">
<Child1 />
</div>
);
}
}
export default App;
Child
import React from 'react'
const Child1 = (props) => {
return (
<div>
</div>
);
}
export default Child1;
If you want to send some data to the parent component upon clicking a button that's in the child component, you can do it this way:
import React from 'react'
const Child1 = React.memo((props) => {
return (
<div>
<button onClick={() => {props.clicked('some data')}} type="button">Click me to send data<button>
</div>
);
})
export default Child1;
now you can assign a function to the clicked prop in your parent component and that gets called when the button in the child component is clicked:
class App extends Component {
state = { message: "" };
callbackFunction = (event) => {
this.setState({
message: event.target.value
});
}
clicked = (data) => { // this func. will be executed
console.log(data);
}
render() {
return (
<div className="App">
<Child1 clicked={this.clicked}/>
</div>
);
}
}
I have founded another solution for you using combine Functional-Class-functional component pass data. here the live code for https://codesandbox.io Click and check that.
Also same code added bellow here:
app component
import React, { useState } from "react";
import "./styles.css";
import Child from "./child";
export default function App() {
const [name, setName] = useState("Orignal Button");
const [count, setCount] = useState(0);
const handleClick = _name => {
setName(_name);
setCount(count + 1);
};
const resetClick = e => {
setName("Orignal Button");
setCount(0);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Child
name={name + " - " + count}
handleClick={handleClick}
resetClick={resetClick}
/>
</div>
);
}
child1 component
import React from "react";
import Child2 from "./child2";
class Child extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<>
<h2>This is child</h2>
<button onClick={e => this.props.handleClick("New Name changed")}>
{this.props.name}
</button>
<Child2 handleChilc2Click={this.props.resetClick} />
</>
);
}
}
export default Child;
Another component Child2
import React from "react";
const Child2 = props => {
return (
<>
<h2>Child 2</h2>
<button onClick={e => props.handleChilc2Click(e)}>
Click me for reset Parent default
</button>
</>
);
};
export default Child2;
You can some help from it.
Thanks
You can pass a function to Child (called Counter in the example) that will change Parent state. Since you pass the same reference for this function every time (this.increment) the only Children that will render are those that changed.
const Counter = React.memo(
//use React.memo to create pure component
function Counter({ counter, increment }) {
console.log('rendering:', counter.id)
// can you gues why prop={new reference} is not a problem here
// this won't re render if props didn't
// change because it's a pure component
return (
<div>
<div>counter is {counter.count}</div>
<button onClick={() => increment(counter.id)}>
+
</button>
</div>
)
}
)
class Parent extends React.PureComponent {
state = {
counters: [
{ id: 1, count: 0 },
{ id: 2, count: 0 }
]
}
increment = _id =>
this.setState({
counters: this.state.counters.map(val =>
_id === val.id
? { ...val, count: val.count + 1 }
: val
)
})
render() {
return (
<div>
{this.state.counters.map(counter => (
<Counter
counter={counter}
increment={this.increment}
key={counter.id}
/>
))}
</div>
)
}
}
//render app
ReactDOM.render(<Parent />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Child Component does not refresh when List Array is updated

I am new to React and I've ran into a problem where I am updating an array list in my app component from a function that is called from user input. This is working fine but there is a child component that is get's the content of that list and maps it to buttons that it displays. My problem is then the list is updated in in the app component it the child component dose not update.
This is the code for my app component:
import React from 'react';
import './App.scss';
import DiceSelector from "./components/DiceSelector";
import ListOfDiceTypes from "./shared/list-available-dice";
const DiceToRollList = [];
const RolledTotal = 45;
DiceToRollList.push(ListOfDiceTypes[4]);
DiceToRollList.push(ListOfDiceTypes[4]);
DiceToRollList.push(ListOfDiceTypes[3]);
export default class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="App">
<header className="App-header">
<div className="Dice-Box">
<h2>Select Dice to Roll</h2>
{ListOfDiceTypes.map((dice, index) => (
<DiceSelector
key={"typeList" + index}
dicetype={dice.dicetype}
imagename={dice.imageName}
maxvalue={dice.maxvalue}
onClick={AddDieClick}
/>
))}
</div>
<div className="Dice-Box">
<h2>Selected Dice</h2>
{DiceToRollList.map((dice, index) => (
<DiceSelector
key={"SelectedList" + index}
dicetype={dice.dicetype}
imagename={dice.imageName}
maxvalue={dice.maxvalue}
onClick={RemoveDieClick}
/>
))}
<h3>Total Rolled = {RolledTotal}</h3>
</div>
</header>
</div>
);
}
}
And here is my child component:
import React from "react";
export default class DiceSelector extends React.Component {
constructor(props) {
super(props);
}
render() {
return <button
className="number"
onClick={() => this.props.onClick(this.props.dicetype)}
>
<img src={require(`../images/${this.props.imagename}`)} alt={this.props.imagename} />
</button>
}
}
You can store key in state of App component and use different key each time when you update props that you are going to pass child component at
<DiceSelector
key= { this.state.key+ offset + index} // insted of {"typeList" + index}
dicetype={dice.dicetype}
imagename={dice.imageName}
maxvalue={dice.maxvalue}
onClick={AddDieClick} // or onClick={RemoveDieClick}
/>
// offset is used to escape duplicate elements next time when child component will render
// offset is the length of the array on that you are mapping
You can add logic of update of key in clickHandler methods
This will rerender the child component.
Or you can use componentWillReceiveProps method to update the state of child component when props changes.
I had a couple of things wrong here. I realized that I did not need the child to refresh when I updated the list I needed the app component to refresh. Also I had functions outside of the app class declared as function functionName(){} rather than in the class as functionName = () = {}. This was keeping me from properly accessing this.state. Finally I was binding to the DiceToRollList rather than this.sate.DiceToRollList. Here is how I updated the app component.
import React, { Component } from 'react';
import './App.scss';
import DiceSelector from "./components/DiceSelector";
import ListOfDiceTypes from "./shared/list-available-dice";
const DiceToRollList = [];
const RolledTotal = 45;
DiceToRollList.push(ListOfDiceTypes[4]);
DiceToRollList.push(ListOfDiceTypes[4]);
DiceToRollList.push(ListOfDiceTypes[3]);
const offset1 = 100;
const offset2 = 500;
export default class App extends Component {
constructor(props) {
super(props);
this.state = { DiceToRollList }
}
render() {
return (
<div className="App">
<header className="App-header">
<div className="Dice-Box">
<h2>Select Dice to Roll</h2>
{ListOfDiceTypes.map((dice, index) => (
<DiceSelector
key={ListOfDiceTypes.length + index} // insted of {"typeList" + index}
dicetype={dice.dicetype}
imagename={dice.imageName}
maxvalue={dice.maxvalue}
onClick={this.AddDieClick}
/>
))}
</div>
<div className="Dice-Box">
<h2>Selected Dice</h2>
{this.state.DiceToRollList.map((dice, index) => (
<DiceSelector
key={this.state.DiceToRollList.length + offset2 + index} // insted of {"dieToRollList" + index}
dicetype={dice.dicetype}
imagename={dice.imageName}
maxvalue={dice.maxvalue}
onClick={this.RemoveDieClick}
/>
))}
<h3>Total Rolled = {RolledTotal}</h3>
</div>
</header>
</div>
);
}
// Functions
AddDieClick = (diceType) => {
let RowToAdd = ListOfDiceTypes.findIndex(obj => {
return obj.dicetype === diceType
});
DiceToRollList.push(ListOfDiceTypes[RowToAdd]);
this.reSetState();
}
reSetState = () => {
this.setState({ DiceToRollList });
};
RemoveDieClick = (diceType) => {
let DieToAdd = DiceToRollList.findIndex(obj => {
return obj.dicetype === diceType
});
DiceToRollList.splice(DiceToRollList[DieToAdd], 1);
this.reSetState();
}
}

Send value to parent component from child component on button click [duplicate]

I'm trying to send data from a child component to it's parent as follow:
const ParentComponent = React.createClass({
getInitialState() {
return {
language: '',
};
},
handleLanguageCode: function(langValue) {
this.setState({language: langValue});
},
render() {
return (
<div className="col-sm-9" >
<SelectLanguage onSelectLanguage={this.handleLanguage}/>
</div>
);
});
and here is the child component:
export const SelectLanguage = React.createClass({
getInitialState: function(){
return{
selectedCode: '',
selectedLanguage: '',
};
},
handleLangChange: function (e) {
var lang = this.state.selectedLanguage;
var code = this.state.selectedCode;
this.props.onSelectLanguage({selectedLanguage: lang});
this.props.onSelectLanguage({selectedCode: code});
},
render() {
var json = require("json!../languages.json");
var jsonArray = json.languages;
return (
<div >
<DropdownList ref='dropdown'
data={jsonArray}
value={this.state.selectedLanguage}
caseSensitive={false}
minLength={3}
filter='contains'
onChange={this.handleLangChange} />
</div>
);
}
});
What I need is to get the selected value by user in the parent component. I'm getting this error:
Uncaught TypeError: this.props.onSelectLanguage is not a function
Can anyone help me to find the problem?
P.S. The child component is creating a dropdown from a json file, and I need the dropdown list to show both elements of the json array next to each other(like: "aaa,english" as the first choice!)
{
"languages":[
[
"aaa",
"english"
],
[
"aab",
"swedish"
],
}
This should work. While sending the prop back you are sending that as an object rather send that as a value or alternatively use it as an object in the parent component. Secondly you need to format your json object to contain name value pairs and use valueField and textField attribute of DropdownList
Short Answer
Parent:
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
Child:
handleLangChange = () => {
var lang = this.dropdown.value;
this.props.onSelectLanguage(lang);
}
Detailed:
EDIT:
Considering React.createClass is deprecated from v16.0 onwards, It is better to go ahead and create a React Component by extending React.Component. Passing data from child to parent component with this syntax will look like
Parent
class ParentComponent extends React.Component {
state = { language: '' }
handleLanguage = (langValue) => {
this.setState({language: langValue});
}
render() {
return (
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
)
}
}
Child
var json = require("json!../languages.json");
var jsonArray = json.languages;
export class SelectLanguage extends React.Component {
state = {
selectedCode: '',
selectedLanguage: jsonArray[0],
}
handleLangChange = () => {
var lang = this.dropdown.value;
this.props.onSelectLanguage(lang);
}
render() {
return (
<div>
<DropdownList ref={(ref) => this.dropdown = ref}
data={jsonArray}
valueField='lang' textField='lang'
caseSensitive={false}
minLength={3}
filter='contains'
onChange={this.handleLangChange} />
</div>
);
}
}
Using createClass syntax which the OP used in his answer
Parent
const ParentComponent = React.createClass({
getInitialState() {
return {
language: '',
};
},
handleLanguage: function(langValue) {
this.setState({language: langValue});
},
render() {
return (
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
);
});
Child
var json = require("json!../languages.json");
var jsonArray = json.languages;
export const SelectLanguage = React.createClass({
getInitialState: function() {
return {
selectedCode: '',
selectedLanguage: jsonArray[0],
};
},
handleLangChange: function () {
var lang = this.refs.dropdown.value;
this.props.onSelectLanguage(lang);
},
render() {
return (
<div>
<DropdownList ref='dropdown'
data={jsonArray}
valueField='lang' textField='lang'
caseSensitive={false}
minLength={3}
filter='contains'
onChange={this.handleLangChange} />
</div>
);
}
});
JSON:
{
"languages":[
{
"code": "aaa",
"lang": "english"
},
{
"code": "aab",
"lang": "Swedish"
},
]
}
To pass data from child component to parent component
In Parent Component:
getData(val){
// do not forget to bind getData in constructor
console.log(val);
}
render(){
return(<Child sendData={this.getData}/>);
}
In Child Component:
demoMethod(){
this.props.sendData(value);
}
Considering React Function Components and using Hooks are getting more popular these days , I will give a simple example of how to Passing data from child to parent component
in Parent Function Component we will have :
import React, { useState } from "react";
then
const [childData, setChildData] = useState("");
and passing setChildData (which do a job similar to this.setState in Class Components) to Child
return( <ChildComponent passChildData={setChildData} /> )
in Child Component first we get the receiving props
function ChildComponent(props){ return (...) }
then you can pass data anyhow like using a handler function
const functionHandler = (data) => {
props.passChildData(data);
}
in React v16.8+ function component, you can use useState() to create a function state that lets you update the parent state, then pass it on to child as a props attribute, then inside the child component you can trigger the parent state function, the following is a working snippet:
const { useState , useEffect } = React;
function Timer({ setParentCounter }) {
const [counter, setCounter] = React.useState(0);
useEffect(() => {
let countersystem;
countersystem = setTimeout(() => setCounter(counter + 1), 1000);
return () => {
clearTimeout(countersystem);
};
}, [counter]);
return (
<div className="App">
<button
onClick={() => {
setParentCounter(counter);
}}
>
Set parent counter value
</button>
<hr />
<div>Child Counter: {counter}</div>
</div>
);
}
function App() {
const [parentCounter, setParentCounter] = useState(0);
return (
<div className="App">
Parent Counter: {parentCounter}
<hr />
<Timer setParentCounter={setParentCounter} />
</div>
);
}
ReactDOM.render(<App />, document.getElementById('react-root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>
You can create the state in the ParentComponent using useState and pass down the setIsParentData function as prop into the ChildComponent.
In the ChildComponent, update the data using the received function through prop to send the data back to ParentComponent.
I use this technique especially when my code in the ParentComponent is getting too long, therefore I will create child components from the ParentComponent. Typically, it will be only 1 level down and using useContext or redux seems overkill in order to share states between components.
ParentComponent.js
import React, { useState } from 'react';
import ChildComponent from './ChildComponent';
export function ParentComponent(){
const [isParentData, setIsParentData] = useState(True);
return (
<p>is this a parent data?: {isParentData}</p>
<ChildComponent toChild={isParentData} sendToParent={setIsParentData} />
);
}
ChildComponent.js
import React from 'react';
export function ChildComponent(props){
return (
<button onClick={() => {props.sendToParent(False)}}>Update</button>
<p>The state of isParentData is {props.toChild}</p>
);
};
I found the approach how to get data from child component in parents when i need it.
Parent:
class ParentComponent extends Component{
onSubmit(data) {
let mapPoint = this.getMapPoint();
}
render(){
return (
<form onSubmit={this.onSubmit.bind(this)}>
<ChildComponent getCurrentPoint={getMapPoint => {this.getMapPoint = getMapPoint}} />
<input type="submit" value="Submit" />
</form>
)
}
}
Child:
class ChildComponent extends Component{
constructor(props){
super(props);
if (props.getCurrentPoint){
props.getCurrentPoint(this.getMapPoint.bind(this));
}
}
getMapPoint(){
return this.Point;
}
}
This example showing how to pass function from child component to parent and use this function to get data from child.
from child component to parent component as below
parent component
class Parent extends React.Component {
state = { message: "parent message" }
callbackFunction = (childData) => {
this.setState({message: childData})
},
render() {
return (
<div>
<Child parentCallback = {this.callbackFunction}/>
<p> {this.state.message} </p>
</div>
);
}
}
child component
class Child extends React.Component{
sendBackData = () => {
this.props.parentCallback("child message");
},
render() {
<button onClick={sendBackData}>click me to send back</button>
}
};
I hope this work
Found a great and easy way to do this with input recently.
Essentially I just useState and then set onChange as a prop to the child comp it takes "value" as an argument and puts it into the useState "setVal" boom I got state change child -> parent every time
const Parent = () => {
const [val, setVal] = useState("initial value")
return(
<>
<Child onChange={(value)=> setVal(value)}/>
<div>{val}</div>
</>
)
};
export default Parent;
const Child = (props) => {
return(
<button onClick={() => props.onChange("your value here") }>
)
}
Here I am trying to explain in simplest way:
I am updating the Parent Component counter from the Child Component.
Parent Component (PropsApp.jsx)
import React, { useState } from 'react'
import Child from './Child'
export default function PropsApp(){
const [counter, setCounter] = useState(0)
const updateMyCounter = () => {
setCounter(counter + 1)
}
return(
<>
<hr></hr>
<h1>This is Parent</h1>
<h2>{counter}</h2>
<Child updateParent={updateMyCounter} />
</>
)
}
Child Component (Child.jsx)
export default function Child(props){
return(
<>
<hr></hr>
<h1>This is Child</h1>
<button
onClick={props.updateParent}
>
Update Parent Component
</button>
</>
)
}
Click on the Update Parent Component and see the magic
React.createClass method has been deprecated in the new version of React, you can do it very simply in the following way make one functional component and another class component to maintain state:
Parent:
const ParentComp = () => {
getLanguage = (language) => {
console.log('Language in Parent Component: ', language);
}
<ChildComp onGetLanguage={getLanguage}
};
Child:
class ChildComp extends React.Component {
state = {
selectedLanguage: ''
}
handleLangChange = e => {
const language = e.target.value;
thi.setState({
selectedLanguage = language;
});
this.props.onGetLanguage({language});
}
render() {
const json = require("json!../languages.json");
const jsonArray = json.languages;
const selectedLanguage = this.state;
return (
<div >
<DropdownList ref='dropdown'
data={jsonArray}
value={tselectedLanguage}
caseSensitive={false}
minLength={3}
filter='contains'
onChange={this.handleLangChange} />
</div>
);
}
};
The idea is to send a callback to the child which will be called to give the data back
A complete and minimal example using functions:
App will create a Child which will compute a random number and send it back directly to the parent, which will console.log the result
const Child = ({ handleRandom }) => {
handleRandom(Math.random())
return <span>child</span>
}
const App = () => <Child handleRandom={(num) => console.log(num)}/>
To pass data from a child component to a Parent component in React:
Pass a function to the child from the parent that receives values.
When the values change in the child component call the function
with the updated values.
e.g.
const Parent = () => {
const handleChange = values => {
alert(JSON.stringify(values) );
//do something with the values
}
return (
<Child handleChange={handleChange} />
);
}
const Child = ({handleChange}) => {
return (
<button onClick={()=> handleChange('values you wish to pass') }}></button>
);
}
NB: As of react 16 I would recommend using functional components in almost all cases.
You can even avoid the function at the parent updating the state directly
In Parent Component:
render(){
return(<Child sendData={ v => this.setState({item: v}) } />);
}
In the Child Component:
demoMethod(){
this.props.sendData(value);
}
Pass data from child to parent Component using Callback
You need to pass from parent to child callback function, and then call it in the child.
Parent Component:-TimeModal
handleTimeValue = (timeValue) => {
this.setState({pouringDiff: timeValue});
}
<TimeSelection
prePourPreHours={prePourPreHours}
setPourTime={this.setPourTime}
isPrePour={isPrePour}
isResident={isResident}
isMilitaryFormatTime={isMilitaryFormatTime}
communityDateTime={moment(communityDT).format("MM/DD/YYYY hh:mm A")}
onSelectPouringTimeDiff={this.handleTimeValue}
/>
Note:- onSelectPouringTimeDiff={this.handleTimeValue}
In the Child Component call props when required
componentDidMount():void{
// Todo use this as per your scenrio
this.props.onSelectPouringTimeDiff(pouringDiff);
}
You are passing a wrong function to child component and your parent class doesn't have handleLanguage function. You can pass like this instead: <SelectLanguage onSelectLanguage={this.handleLanguageChange}/>. I think if a function is absent in a class its would would be None.
your parent component should be like this :
render() {
return (
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
);
}
Best way to pass data from child to parent component
child component
handleLanguageCode=()=>(langValue) {
this.props.sendDatatoParent(langValue)
}
Parent
<Parent sendDatatoParent={ data => this.setState({item: data}) } />;
import { useEffect, useState } from "react";
export default function App() {
const data = (data) => {
console.log("data", data);
};
const myData = {
name: "hi this is my data"
};
return <Form onSubmit={data} myDatasa={myData} />;
}
const Form = (props) => {
console.log("myData", props.myDatasa.name);
const [choreDesc, setChoreDesc] = useState();
const handleSubmit = (e) => {
e.preventDefault();
props.onSubmit(choreDesc);
};
const handlechange = (e) => {
setChoreDesc(e.target.value);
};
return (
<form
onSubmit={(e) => {
handleSubmit(e);
}}
>
<label>Chore description:</label>
<br />
<input
name="choreDesc"
type="text"
value={choreDesc}
onChange={handlechange}
/>
<br />
<input type="submit" value="Add Log" />
</form>
);
};
```
Passing Data between Parent and Child Component in React Hook
Passing the function to child,
and wait child passing back the value by calling parent's function
parent (../app.js)
import MyCOMP from "../component/MyCOMP"; //import child component
export default function MyMainPage() {
return(
<>
<MyCOMP
//pass function to child and wait child passback the changed value
// 1.Click child component passing function to child
ParentFunction={(x)=>{
console.log('Child Pass Back Value',x)
// 3. Parent received data
// after you get the value change you can ultilize another function, useEffect or useState
}}/>
</>
)
}
child (../component/MyCOMP.js)
export default function MyCOMP({ParentFunction}){
return(
<>
<button onClick={()=>{
// 2. Child passing back value to parent
ParentFunction("Child reply ANSWER is ","fm 99.8");}}>Click Me</button>
</>
)
}
Result
after click the button, parent class show "fm 99.8" sting value (the
child's value)
Please comment below, if it help you, or you got another idea

How to pass data from child component to its parent in ReactJS?

I'm trying to send data from a child component to it's parent as follow:
const ParentComponent = React.createClass({
getInitialState() {
return {
language: '',
};
},
handleLanguageCode: function(langValue) {
this.setState({language: langValue});
},
render() {
return (
<div className="col-sm-9" >
<SelectLanguage onSelectLanguage={this.handleLanguage}/>
</div>
);
});
and here is the child component:
export const SelectLanguage = React.createClass({
getInitialState: function(){
return{
selectedCode: '',
selectedLanguage: '',
};
},
handleLangChange: function (e) {
var lang = this.state.selectedLanguage;
var code = this.state.selectedCode;
this.props.onSelectLanguage({selectedLanguage: lang});
this.props.onSelectLanguage({selectedCode: code});
},
render() {
var json = require("json!../languages.json");
var jsonArray = json.languages;
return (
<div >
<DropdownList ref='dropdown'
data={jsonArray}
value={this.state.selectedLanguage}
caseSensitive={false}
minLength={3}
filter='contains'
onChange={this.handleLangChange} />
</div>
);
}
});
What I need is to get the selected value by user in the parent component. I'm getting this error:
Uncaught TypeError: this.props.onSelectLanguage is not a function
Can anyone help me to find the problem?
P.S. The child component is creating a dropdown from a json file, and I need the dropdown list to show both elements of the json array next to each other(like: "aaa,english" as the first choice!)
{
"languages":[
[
"aaa",
"english"
],
[
"aab",
"swedish"
],
}
This should work. While sending the prop back you are sending that as an object rather send that as a value or alternatively use it as an object in the parent component. Secondly you need to format your json object to contain name value pairs and use valueField and textField attribute of DropdownList
Short Answer
Parent:
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
Child:
handleLangChange = () => {
var lang = this.dropdown.value;
this.props.onSelectLanguage(lang);
}
Detailed:
EDIT:
Considering React.createClass is deprecated from v16.0 onwards, It is better to go ahead and create a React Component by extending React.Component. Passing data from child to parent component with this syntax will look like
Parent
class ParentComponent extends React.Component {
state = { language: '' }
handleLanguage = (langValue) => {
this.setState({language: langValue});
}
render() {
return (
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
)
}
}
Child
var json = require("json!../languages.json");
var jsonArray = json.languages;
export class SelectLanguage extends React.Component {
state = {
selectedCode: '',
selectedLanguage: jsonArray[0],
}
handleLangChange = () => {
var lang = this.dropdown.value;
this.props.onSelectLanguage(lang);
}
render() {
return (
<div>
<DropdownList ref={(ref) => this.dropdown = ref}
data={jsonArray}
valueField='lang' textField='lang'
caseSensitive={false}
minLength={3}
filter='contains'
onChange={this.handleLangChange} />
</div>
);
}
}
Using createClass syntax which the OP used in his answer
Parent
const ParentComponent = React.createClass({
getInitialState() {
return {
language: '',
};
},
handleLanguage: function(langValue) {
this.setState({language: langValue});
},
render() {
return (
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
);
});
Child
var json = require("json!../languages.json");
var jsonArray = json.languages;
export const SelectLanguage = React.createClass({
getInitialState: function() {
return {
selectedCode: '',
selectedLanguage: jsonArray[0],
};
},
handleLangChange: function () {
var lang = this.refs.dropdown.value;
this.props.onSelectLanguage(lang);
},
render() {
return (
<div>
<DropdownList ref='dropdown'
data={jsonArray}
valueField='lang' textField='lang'
caseSensitive={false}
minLength={3}
filter='contains'
onChange={this.handleLangChange} />
</div>
);
}
});
JSON:
{
"languages":[
{
"code": "aaa",
"lang": "english"
},
{
"code": "aab",
"lang": "Swedish"
},
]
}
To pass data from child component to parent component
In Parent Component:
getData(val){
// do not forget to bind getData in constructor
console.log(val);
}
render(){
return(<Child sendData={this.getData}/>);
}
In Child Component:
demoMethod(){
this.props.sendData(value);
}
Considering React Function Components and using Hooks are getting more popular these days , I will give a simple example of how to Passing data from child to parent component
in Parent Function Component we will have :
import React, { useState } from "react";
then
const [childData, setChildData] = useState("");
and passing setChildData (which do a job similar to this.setState in Class Components) to Child
return( <ChildComponent passChildData={setChildData} /> )
in Child Component first we get the receiving props
function ChildComponent(props){ return (...) }
then you can pass data anyhow like using a handler function
const functionHandler = (data) => {
props.passChildData(data);
}
in React v16.8+ function component, you can use useState() to create a function state that lets you update the parent state, then pass it on to child as a props attribute, then inside the child component you can trigger the parent state function, the following is a working snippet:
const { useState , useEffect } = React;
function Timer({ setParentCounter }) {
const [counter, setCounter] = React.useState(0);
useEffect(() => {
let countersystem;
countersystem = setTimeout(() => setCounter(counter + 1), 1000);
return () => {
clearTimeout(countersystem);
};
}, [counter]);
return (
<div className="App">
<button
onClick={() => {
setParentCounter(counter);
}}
>
Set parent counter value
</button>
<hr />
<div>Child Counter: {counter}</div>
</div>
);
}
function App() {
const [parentCounter, setParentCounter] = useState(0);
return (
<div className="App">
Parent Counter: {parentCounter}
<hr />
<Timer setParentCounter={setParentCounter} />
</div>
);
}
ReactDOM.render(<App />, document.getElementById('react-root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>
You can create the state in the ParentComponent using useState and pass down the setIsParentData function as prop into the ChildComponent.
In the ChildComponent, update the data using the received function through prop to send the data back to ParentComponent.
I use this technique especially when my code in the ParentComponent is getting too long, therefore I will create child components from the ParentComponent. Typically, it will be only 1 level down and using useContext or redux seems overkill in order to share states between components.
ParentComponent.js
import React, { useState } from 'react';
import ChildComponent from './ChildComponent';
export function ParentComponent(){
const [isParentData, setIsParentData] = useState(True);
return (
<p>is this a parent data?: {isParentData}</p>
<ChildComponent toChild={isParentData} sendToParent={setIsParentData} />
);
}
ChildComponent.js
import React from 'react';
export function ChildComponent(props){
return (
<button onClick={() => {props.sendToParent(False)}}>Update</button>
<p>The state of isParentData is {props.toChild}</p>
);
};
I found the approach how to get data from child component in parents when i need it.
Parent:
class ParentComponent extends Component{
onSubmit(data) {
let mapPoint = this.getMapPoint();
}
render(){
return (
<form onSubmit={this.onSubmit.bind(this)}>
<ChildComponent getCurrentPoint={getMapPoint => {this.getMapPoint = getMapPoint}} />
<input type="submit" value="Submit" />
</form>
)
}
}
Child:
class ChildComponent extends Component{
constructor(props){
super(props);
if (props.getCurrentPoint){
props.getCurrentPoint(this.getMapPoint.bind(this));
}
}
getMapPoint(){
return this.Point;
}
}
This example showing how to pass function from child component to parent and use this function to get data from child.
from child component to parent component as below
parent component
class Parent extends React.Component {
state = { message: "parent message" }
callbackFunction = (childData) => {
this.setState({message: childData})
},
render() {
return (
<div>
<Child parentCallback = {this.callbackFunction}/>
<p> {this.state.message} </p>
</div>
);
}
}
child component
class Child extends React.Component{
sendBackData = () => {
this.props.parentCallback("child message");
},
render() {
<button onClick={sendBackData}>click me to send back</button>
}
};
I hope this work
Found a great and easy way to do this with input recently.
Essentially I just useState and then set onChange as a prop to the child comp it takes "value" as an argument and puts it into the useState "setVal" boom I got state change child -> parent every time
const Parent = () => {
const [val, setVal] = useState("initial value")
return(
<>
<Child onChange={(value)=> setVal(value)}/>
<div>{val}</div>
</>
)
};
export default Parent;
const Child = (props) => {
return(
<button onClick={() => props.onChange("your value here") }>
)
}
Here I am trying to explain in simplest way:
I am updating the Parent Component counter from the Child Component.
Parent Component (PropsApp.jsx)
import React, { useState } from 'react'
import Child from './Child'
export default function PropsApp(){
const [counter, setCounter] = useState(0)
const updateMyCounter = () => {
setCounter(counter + 1)
}
return(
<>
<hr></hr>
<h1>This is Parent</h1>
<h2>{counter}</h2>
<Child updateParent={updateMyCounter} />
</>
)
}
Child Component (Child.jsx)
export default function Child(props){
return(
<>
<hr></hr>
<h1>This is Child</h1>
<button
onClick={props.updateParent}
>
Update Parent Component
</button>
</>
)
}
Click on the Update Parent Component and see the magic
React.createClass method has been deprecated in the new version of React, you can do it very simply in the following way make one functional component and another class component to maintain state:
Parent:
const ParentComp = () => {
getLanguage = (language) => {
console.log('Language in Parent Component: ', language);
}
<ChildComp onGetLanguage={getLanguage}
};
Child:
class ChildComp extends React.Component {
state = {
selectedLanguage: ''
}
handleLangChange = e => {
const language = e.target.value;
thi.setState({
selectedLanguage = language;
});
this.props.onGetLanguage({language});
}
render() {
const json = require("json!../languages.json");
const jsonArray = json.languages;
const selectedLanguage = this.state;
return (
<div >
<DropdownList ref='dropdown'
data={jsonArray}
value={tselectedLanguage}
caseSensitive={false}
minLength={3}
filter='contains'
onChange={this.handleLangChange} />
</div>
);
}
};
The idea is to send a callback to the child which will be called to give the data back
A complete and minimal example using functions:
App will create a Child which will compute a random number and send it back directly to the parent, which will console.log the result
const Child = ({ handleRandom }) => {
handleRandom(Math.random())
return <span>child</span>
}
const App = () => <Child handleRandom={(num) => console.log(num)}/>
To pass data from a child component to a Parent component in React:
Pass a function to the child from the parent that receives values.
When the values change in the child component call the function
with the updated values.
e.g.
const Parent = () => {
const handleChange = values => {
alert(JSON.stringify(values) );
//do something with the values
}
return (
<Child handleChange={handleChange} />
);
}
const Child = ({handleChange}) => {
return (
<button onClick={()=> handleChange('values you wish to pass') }}></button>
);
}
NB: As of react 16 I would recommend using functional components in almost all cases.
You can even avoid the function at the parent updating the state directly
In Parent Component:
render(){
return(<Child sendData={ v => this.setState({item: v}) } />);
}
In the Child Component:
demoMethod(){
this.props.sendData(value);
}
Pass data from child to parent Component using Callback
You need to pass from parent to child callback function, and then call it in the child.
Parent Component:-TimeModal
handleTimeValue = (timeValue) => {
this.setState({pouringDiff: timeValue});
}
<TimeSelection
prePourPreHours={prePourPreHours}
setPourTime={this.setPourTime}
isPrePour={isPrePour}
isResident={isResident}
isMilitaryFormatTime={isMilitaryFormatTime}
communityDateTime={moment(communityDT).format("MM/DD/YYYY hh:mm A")}
onSelectPouringTimeDiff={this.handleTimeValue}
/>
Note:- onSelectPouringTimeDiff={this.handleTimeValue}
In the Child Component call props when required
componentDidMount():void{
// Todo use this as per your scenrio
this.props.onSelectPouringTimeDiff(pouringDiff);
}
You are passing a wrong function to child component and your parent class doesn't have handleLanguage function. You can pass like this instead: <SelectLanguage onSelectLanguage={this.handleLanguageChange}/>. I think if a function is absent in a class its would would be None.
your parent component should be like this :
render() {
return (
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
);
}
Best way to pass data from child to parent component
child component
handleLanguageCode=()=>(langValue) {
this.props.sendDatatoParent(langValue)
}
Parent
<Parent sendDatatoParent={ data => this.setState({item: data}) } />;
import { useEffect, useState } from "react";
export default function App() {
const data = (data) => {
console.log("data", data);
};
const myData = {
name: "hi this is my data"
};
return <Form onSubmit={data} myDatasa={myData} />;
}
const Form = (props) => {
console.log("myData", props.myDatasa.name);
const [choreDesc, setChoreDesc] = useState();
const handleSubmit = (e) => {
e.preventDefault();
props.onSubmit(choreDesc);
};
const handlechange = (e) => {
setChoreDesc(e.target.value);
};
return (
<form
onSubmit={(e) => {
handleSubmit(e);
}}
>
<label>Chore description:</label>
<br />
<input
name="choreDesc"
type="text"
value={choreDesc}
onChange={handlechange}
/>
<br />
<input type="submit" value="Add Log" />
</form>
);
};
```
Passing Data between Parent and Child Component in React Hook
Passing the function to child,
and wait child passing back the value by calling parent's function
parent (../app.js)
import MyCOMP from "../component/MyCOMP"; //import child component
export default function MyMainPage() {
return(
<>
<MyCOMP
//pass function to child and wait child passback the changed value
// 1.Click child component passing function to child
ParentFunction={(x)=>{
console.log('Child Pass Back Value',x)
// 3. Parent received data
// after you get the value change you can ultilize another function, useEffect or useState
}}/>
</>
)
}
child (../component/MyCOMP.js)
export default function MyCOMP({ParentFunction}){
return(
<>
<button onClick={()=>{
// 2. Child passing back value to parent
ParentFunction("Child reply ANSWER is ","fm 99.8");}}>Click Me</button>
</>
)
}
Result
after click the button, parent class show "fm 99.8" sting value (the
child's value)
Please comment below, if it help you, or you got another idea

Resources