Reputation: 45
I am using a component inside a component. It is well know that how to send data to child component. But how can I return back values from the child component to the parent component? I read componentDidMount
, componentWillMount
, but I am still confused in understanding how can I return back values to parent component from child component.
In my following code, please help me to return back a value from the child Catalog.jsx to the Parent component AppWrapper.jsx. Such that, I want to to return back from the function ProductButtonClicked
at Catalog.jsx the state value number_ofItems
to AppWrapper.jsx state value itemsAdded
Note: At AppWrapper.jsx, there is
Here is my Catalog.jsx file
var React = require('react');
var Parse = require('parse').Parse;
var ParseReact = require('parse-react');
var cookie = require('react-cookie');
var Catalog = React.createClass({
mixins: [ParseReact.Mixin],
getInitialState: function() {
return {
// if the cookie is there, It will return the cookie value which I saved as 'true' word.
FTWVeyCc4o: cookie.load('RahlTradingProductID-FTWVeyCc4o'),
aJ3DoJp352: cookie.load('RahlTradingProductID-aJ3DoJp352'),
dgeRhSG21U: cookie.load('RahlTradingProductID-dgeRhSG21U'),
number_ofItems: 0
};
},
componentDidMount: function() {
this.noOfItemsAdded();
},
//Observe Function - a newly proposed function for prarse react integration
observe: function() {
//declare any variable you need here.
return {
product: (new Parse.Query('product'))
.ascending('createdAt')
};
},
//Render
render: function() {
var content = (
<div>
no product
</div>
);
if(this.data.product.length){
var content = (
<div>
{ // Products are listed in this
this.data.product.map(function(p) {
return (
// <div>man</div>
//From Design
<div className="col-md-4">
<div className="item text-center">
<div className="photo">
<img src={ p.productImgUrl } />
<br /><br />
<h5>{p.name} <br /> {p.size}</h5>
</div>
</div>
<div className="action">
<button
type="button"
className={"btn btn-"
+ (
(this.state.FTWVeyCc4o && (p.objectId == "FTWVeyCc4o")) || (this.state.aJ3DoJp352 && (p.objectId == "aJ3DoJp352")) || (this.state.dgeRhSG21U && (p.objectId == "dgeRhSG21U")) ? 'warning' : 'primary'
)}
onClick={this.ProductButtonClicked.bind(this, p)}
>
{(
(this.state.FTWVeyCc4o && (p.objectId == "FTWVeyCc4o")) || (this.state.aJ3DoJp352 && (p.objectId == "aJ3DoJp352")) || (this.state.dgeRhSG21U && (p.objectId == "dgeRhSG21U")) ? 'Remove' : 'Add'
)}
</button>
</div>
</div>
);
}, this)}
</div>
);
}
else{
var content = (<div>
</div>);
}
return <div>{content}</div>;
},
ProductButtonClicked:function(obj){
//alert(this.incrementCount())
// a = this.state.bind(obj.objectId);
// if( a == "" )
if( this.getCookiefunc('RahlTradingProductID-' + obj.objectId) == "")
{
//create the cookie
document.cookie="RahlTradingProductID-" + obj.objectId + "=true; expires=Thu, 18 Dec 2017 12:00:00 UTC; path=/";
//update state
if(obj.objectId == "FTWVeyCc4o")
{
this.setState({FTWVeyCc4o:true});
this.setState({number_ofItems: this.state.number_ofItems + 1});
}
else if(obj.objectId == "aJ3DoJp352")
{
this.setState({aJ3DoJp352:true});
this.setState({number_ofItems: this.state.number_ofItems + 1});
}
else if(obj.objectId == "dgeRhSG21U")
{
this.setState({dgeRhSG21U:true});
this.setState({number_ofItems: this.state.number_ofItems + 1});
}
}
else
{//alert("Delete Cookie")
//delete the cookie
document.cookie="RahlTradingProductID-" + obj.objectId + "=; expires=Thu, 18 Dec 2000 12:00:00 UTC; path=/";
if(obj.objectId == "FTWVeyCc4o")
{
this.setState({FTWVeyCc4o:false});
this.setState({number_ofItems: this.state.number_ofItems - 1});
}
else if(obj.objectId == "aJ3DoJp352")
{
this.setState({aJ3DoJp352:false});
this.setState({number_ofItems: this.state.number_ofItems - 1});
}
else if(obj.objectId == "dgeRhSG21U")
{
this.setState({dgeRhSG21U:false});
this.setState({number_ofItems: this.state.number_ofItems - 1});
}
}
},
noOfItemsAdded:function(){
counter= 0;
if(this.state.FTWVeyCc4o)
counter = counter +1;
if(this.state.aJ3DoJp352)
counter = counter +1;
if(this.state.dgeRhSG21U)
counter = counter +1;
this.setState({number_ofItems: counter});
//alert(counter);
},
getCookiefunc:function(cname){
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
}
return "";
}
});
module.exports = Catalog;
And here is my AppWrapper.jsx
var React = require('react');
var Catalog = require('./Catalog');
// var cart = require('./cart');
var contents = [
<Catalog onIncrementCount={this.onIncrementCount}/>
// ,<cart />
];
var AppWrapper = React.createClass({
getInitialState: function() {
return {
currentTab: 0,
count: 0
};
},
onIncrementCount: function() {
this.setState({count: this.state.count + 1});
alert(this.state.count)
},
render: function() {
return (
<div>
<div className="site-wrapper">
<div className="site-wrapper-inner">
<div className="cover-container">
<div className="masthead clearfix">
<div className="inner">
<h3 className="masthead-brand">
<img src="images/naleczowianka-logo.png" />
</h3>
<nav>
<ul className="nav masthead-nav">
<li className="active"><a href="#" >English <span className="glyphicon glyphicon-menu-down"></span></a></li>
<li><a href="#"><span className="glyphicon glyphicon-log-in"></span> Login</a></li>
</ul>
</nav>
</div>
</div>
<br />
<div className="inner cover">
<header className="row">
<div className="col-md-12">
<div className="row">
<div className="col-md-4 col-xs-4"><h4 className="active">Choose Product</h4></div>
<div className="col-md-4 col-xs-4"><h4>
<a href="#">
<span className="glyphicon glyphicon-shopping-cart"> </span>
</a>
<a href="http://www.google.com" className="NavLinks" >Shopping Cart ( {this.state.count} ) </a>
</h4></div>
<div className="col-md-4 col-xs-4"><h4>Order</h4></div>
</div>
<br />
<div className="progress">
<div className="progress-bar progress-bar-striped active width-15" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100" >
<span className="sr-only">15% Complete</span>
</div>
</div>
</div>
</header>
<br />
<main className="row box">
<div className="col-md-12">
<div className="row">
<div >
{contents[this.state.currentTab] }
</div>
<br />
<div className="row">
<div className="col-md-6">
<h4>Still Waters</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
<div className="col-md-6">
<h4>Sparkling Waters</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
</div>
</div>
</div>
</div>
</main>
<div className="mastfoot">
<div className="inner row">
<div className="col-md-4 col-xs-4">
<a href="">Rahl Trading</a>
</div>
<div className="col-md-4 col-xs-4">
<a href="">Frequently Asked Questions</a>
</div>
<div className="col-md-4 col-xs-4">
<a href="">Privacy</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
},
selectTab: function(tab) {
this.setState({ currentTab: tab });
// this.props.tabChanged(tab);
}
});
module.exports = AppWrapper;
Upvotes: 0
Views: 568
Reputation: 1853
In React, you will usually pass data back to the parent by using callbacks as props. Something like this:
var Child = React.createClass({
getDefaultProps: function() {
return {
onIncrementCount: null
};
},
render: function() {
return <button onClick={this.incrementCount}>Increment</button>;
},
incrementCount: function() {
// Some data you want to pass externally
var data = [1,2,3];
this.props.onIncrementCount.call(this, data);
}
});
var Parent = React.createClass({
render: function() {
return (
<div>
<Child onIncrementCount={this.onIncrementCount} />
<div>Count is {this.state.count}</div>
</div>
);
},
getInitialState: function() {
return {
count: 0
};
},
onIncrementCount: function() {
this.setState({count: this.state.count + 1});
}
});
The child takes the callback onIncrementCount
, and the parent passes in its own local function as the callback. The child can then trigger this callback.
Edit:
In regards to your new information, in your ProductButtonClicked
function, you need to store the number_ofItems
in a local variable, then assign setState at the end of your function. So instead of calling setState
, assign it in a similar fashion to this:
var number_ofItems;
if( this.getCookiefunc('RahlTradingProductID-' + obj.objectId) == "")
// Your usual logic here, but set the local variable
number_ofItems = this.state.number_ofItems - 1;
}
// End of your function
this.setState({number_ofItems: number_ofItems});
// Send the data to the parent
this.props.incrementCount(number_ofItems);
However, in your parent function, you need to pass in the incrementCount function as props to the Catalog when it's rendered.
var Parent = React.createClass({
render: function() {
return <Catalog incrementCount={this.incrementCount} />;
},
incrementCount: function(newCount) {
// Finally you can use your newCount here, which was from the child
}
})
Upvotes: 1