how to call function from component that is independent of each other - reactjs

I have 3 components, one parent component which renders 2 child components. I need to access the function of the 1st child component from the 2nd child component.
Sample Code:
Parent Component:
class Main extends React.Component {
myRef: React.RefObject<any>;
constructor(props: any) {
super(props);
this.myRef = React.createRef();
}
return (
<div>
{/* some code */}
<ChildOne />
<ChildTwo />
</div>
);
ChildOne:
function ChildOne() {
const childOneFunction = () => {
console.log("Hello from child one");
};
return <div>{/* some code */}</div>;
}
}
ChildTwo:
function ChildTwo() {
useEffect(() => {
childOneFunction();
});
return <div>{/* some code */}</div>;
}
I need call the childOneFunction() from childTwo component. Is it possible without any 3rd party library like redux?

Maybe you can try with forwarding refs and useImperativeHandle.
Demo:
let ChildOne = React.forwardRef((props, ref) => {
React.useImperativeHandle(ref, () => ({
childOneFunction: () => {
console.log('Hello from child one');
},
}));
return <div>1</div>;
});
let ChildTwo = React.forwardRef((props, ref) => {
return (
<div
onClick={() => {
ref.current.childOneFunction();
}}
>
2
</div>
);
});
export default function App() {
const test = React.useRef();
return (
<div>
<ChildOne ref={test} />
<ChildTwo ref={test} />
</div>
);
}

Related

React - Passing a value from child component to the parent component

Using Hooks, how can I pass the item.id from the child component to the parent component by clicking the button inside the child component?
The parent component:
import React from 'react'
import MyList from '../MyList'
const App = props => {
return (
<div className='App'>
<MyList />
</div>
)
}
export default App
The child component:
import React from 'react'
import jsonResponse from '../data'
function MyList (props) {
const list = jsonResponse.map((item) => {
return (
<li className='list-container' key={item.id}>
<h4>Name: {item.name}</h4>
<button className='btn'>More details</button>
</li>
)
})
return (
<ul id='container'>
{list}
</ul>
)
}
export default MyList
React is all about data flowing down in the components tree. If you want your Child to be able to show and/or modify a shared state between Child and Parent you should lift your state up and pass it down via props to it's children
const Parent = () =>{
const [title, settitle] = useState('foo')
return <Child title={title} setTitle={setTitle} />
}
const Child = ({ title, setTitle}) =>{
return <input value={title} onChange={e => setTitle(e.target.value)} />
}
In class based components
class Parent extends React.Component{
state = { title: '' }
setTitle = title => this.setState({ title })
render(){
const { title } = this.state
return <Child title={title} setTitle={this.setTitle} />
}
}
class Child extends React.Component{
render(){
const { title, setTitle } = this.props
return <input value={value} setTitle={e => setTitle(e.target.value)} />
}
}
But if you really insists that your Child holds the state (anti pattern) you can do something like this
const Parent = () =>{
const [childProp, setChildProp] = useState(null)
return <Child setChildProp={setChildProp} />
}
const Child = ({ setChildProp }) =>{
return <button onClick={() => setChildProp('foo')}>Change to foo</button>
}

React passing props to child and back to parent

My current structure is like this:
state={
activetab=1,
activetab2=2}
<child1 activetab={activetab}/>
<child2 activetab2={activetab2}/>
And I would like when the user changes the active tab from child 2 to update the state on the parent component, and then also handle the change on the child1 component.
child 1 code :
render() {
const activetab=this.props;
this.showimage1 = () => {
if (activetab === 1) {
return (
<img src={slide1} alt='' />
)
} else null;
}
return (
<div>
{this.showimage1()}
</div>
child 2 code :
constructor (props) {
super(props)
this.changetab= this.changetab.bind(this)
this.state={
activetab:1}
}
render () {
const activetab2=this.props;
changetab(tab) {
if (this.state.activeTab !== tab) {
this.setState({
activeTab: tab
})
}
}
return(
<div>
<button onClick={() => {
this.changetab(1)
}}
>tab1 </button>
</div>
So as you can see I want when the user changes the current tab from child 2 to pass the props in my parent component so that the child1 component knows which image to show depending on the tab. Anyone knows how to do it without rewriting everything in a single component?
Create a main component that renders the two component child 1 and 2 create only 1 source of truth means only 1 state to be pass to the child components as props.
export class MainComponent extends Component {
constructor (props) {
super(props)
this.changetab = this.changetab.bind(this)
this.state={
activetab: 0
}
}
changetab(tab) {
if (this.state.activeTab !== tab) {
this.setState({
activeTab: tab
})
}
render() {
return (
<div>
<ChildOne activetab={this.state.activetab} />
<ChildTwo activetab={this.state.activetab} changetab={this.changetab} />
</div>
)
}
}
// ChildOne Component pass state activetab as props
render() {
const { activetab } = this.props;
this.showimage1 = () => {
if (activetab === 1) {
return (
<img src={slide1} alt='' />
)
} else null;
}
return (
<div>
{this.showimage1()}
</div>
// ChildTwo Component
render () {
const { activetab, changetab } = this.props;
return(
<div>
<button onClick={() => {
this.changetab(1)
}}
>tab1 </button>
</div>
The parent component must have 2 function handlechange that you pass to your childs.
Will look something like that
// Parent
class Parent extends React.Component {
// Constructor
constructor(props) {
this.state = {
child1: 1,
child2: 0
};
}
handleChangeChild1(state) {
this.setState({ child1: state });
}
handleChangeChild2(state) {
this.setState({ child2: state });
}
render() {
return (
<div>
<Child1 onXChange={this.handleChangeChild1} />
<Child2 onYChange={this.handleChangeChild2} />
</div>
);
}
}
And in the children you do
class Child extends React.Component {
constructor(props) {
super(props)
}
handleChange(e) = () => {
this.props.onXChange
}
render() {
return (
<input onChange={this.handleChange} />
)
}
}
I recommend you read the doc
You can wrap the components in a parent component. Then you can pass a function from the parent to child 2 by attaching it to a prop. Child 2 can then call this function on a change.
In the parent:
render() {
const someFunction = (someVariable) => {
// do something
}
return(
<child2 somePropName={ this.someFunction } />
)
}
edit: removed .bind() from this example

How to update a child component without re-rendering without Redux

How do I update an adjacent (or child) component after a scroll event without re-rendering the parent component?
Adjacent scenario
<div>
<Scrollable onScroll={ ... } />
<DisplayPosition scrollEvent={ ... } />
</div>
Child scenario
return (
<div onScroll={ ... }>
<span> Don’t re-render me! </span>
<DisplayPosition scrollEvent={ ... } />
</div>
)
I am reluctant to reach for Redux for this problem as I would like to be able to solve it in a lightweight fashion
Without Redux
ParentComponent
export default class ParentComponent extends Component {
render() {
let parentCallback = () => {};
const onScroll = event => parentCallback(event);
const didScroll = callback => parentCallback = callback;
return (<div onScroll={onScroll}>
<ChildrenComponent whenParent={didScroll} />
...
ChildrenComponent
It will setup the callback to be executed by the parent
componentDidMount() {
this.props.whenParent(event => this.setState({ event }));
}
By updating the state your ChildrenComponent will re-render. The ParentComponent will not re-render as nothing on its state or properties changed.
You'll have access to your event on this.state.event. Check the snippet for an example with click event.
class ParentComponent extends React.Component {
render() {
console.log('hello ParentComponent');
let parentCallback = () => {};
const onClick = () => parentCallback(1);
const didClick = callback => parentCallback = callback;
return (
<div>
<button onClick={onClick}>Click To Add</button>
<ChildrenComponent whenParent={didClick} />
</div>
);
}
}
class ChildrenComponent extends React.Component {
state = { sum: 0 };
componentDidMount() {
const { whenParent } = this.props;
whenParent((adds) => {
const { sum } = this.state;
this.setState({ sum: sum + adds });
});
}
render() {
console.log('hello ChildrenComponent');
const { sum } = this.state;
return <div>{sum}</div>;
}
}
ReactDOM.render(
<ParentComponent />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>

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