Passing props from child to parent class component in React - reactjs

My child class is ChangeProps and parent is ParentClass
class ChangeProps extends React.Component{
render(){
return(
<div>
<h2>{this.props.childname}</h2>
<button onClick={()=>this.props.onNameChange()}>Change</button>
</div>
);
}
}
class ParentClass extends React.Component{
constructor(props){
super(props);
this.state={
name:'parent name'
}
this.onChange=this.onChange(this);
}
onChange=(newName)=>
{
this.setState({ name: newName });
}
render(){
return(
<div>
<ChangeProps childname={this.state.name} onNameChange={this.onChange}/>
</div>
);
}
}
When I click on the button to change the state, name doesn't change. I got the below error:
TypeError: this.props.onNameChange is not a function

since you are using arrow functions you dont have to explicitly define the scope so commenting the line this.onChange=this.onChange(this); would work
class ParentClass extends React.Component{
constructor(props){
super(props);
this.state={
name:'parent name'
}
//this.onChange=this.onChange(this);//comment this line
}
onChange=(newName)=>
{
this.setState({ name: newName });
}
render(){
return(
<div>
<ChangeProps childname={this.state.name} onNameChange={this.onChange}/>
</div>
);
}
}
Here is the working demo
Or else
class ParentClass extends React.Component{
constructor(props){
super(props);
this.state={
name:'parent name'
}
this.onChange = this.onChange.bind(this);//bind the function to the scope
}
onChange(newName) {//keep this as regular function
this.setState({ name: newName });
}
render(){
return(
<div>
<ChangeProps childname={this.state.name} onNameChange={this.onChange}/>
</div>
);
}
}

Related

ReactJS: pass data through 3 components

I'm trying to pass data through 3 components within the hierarchy (Parent-Child-Child2):
Parent-class:
class Parent extends React.Component {
constructor(props) {
super(props);
this.handleOperation = this.handleOperation.bind(this);
}
handleOperation = (value) => {
// some actions
};
render() {
return (
<div className={styles}>
<Child valueChild={this.handleOperation()}/>
</div>
);
}
}
Child1:
class Child extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange =(value) => {
this.props.valueChild(value);
};
render() {
return (
<div>
<Child2 childValue2 = {this.handleChange} />
</div>
);
}
}
Child2:
class Child2 extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange =(event) => {
this.props.childValue2(event.target.value);
};
render() {
return (
<div>
<input type="button" onClick={this.handleChange} value="defaultValue" />
</div>
);
}
}
Code compiling successfully, but when I click on input-field (to pass value to Parent), I receive the following error:

Passing data from parent to child reactjs?

How to pass data from parent to child. why this is not working?
cannot display data in child component
class App extends React.Component {
constructor(props){
super(props);
const customers = [ 'Guacamole', 'Beef', 'Bean' ];
}
render() {
return (
<div>
1) DataGrid
<Api customers = {this.customers} />
</div>
);
}
}
export default App;
class Api extends React.Component {
render() {
return (
<div>
{this.props.customers}
</div>
)}
}
Why this is not working? Because this.customers === null
How to pass data from parent to child?
Either use constant properly
class App extends React.Component {
constructor(props){
super(props);
}
render() {
const customers = [ 'Guacamole', 'Beef', 'Bean' ];
return (
<div>
1) DataGrid
<Api customers = {customers} />
</div>
);
}
}
export default App;
class Api extends React.Component {
render() {
return (
<div>
{this.props.customers}
</div>
)}
}
Or use state properly:
class App extends React.Component {
constructor(props){
super(props);
this.state = {
customers: [ 'Guacamole', 'Beef', 'Bean' ],
};
}
render() {
return (
<div>
1) DataGrid
<Api customers = {this.state.customers} />
<div onClick={() => {this.setState({customers: ['Beef', 'Apple']})}}>Change state</div>
</div>
);
}
}
export default App;
class Api extends React.Component {
render() {
return (
<div>
{this.props.customers}
</div>
)}
}
Or use this properly:
class App extends React.Component {
constructor(props){
super(props);
this.customers = [ 'Guacamole', 'Beef', 'Bean' ];
}
render() {
return (
<div>
1) DataGrid
<Api customers = {this.customers} />
</div>
);
}
}
export default App;
class Api extends React.Component {
render() {
return (
<div>
{this.props.customers}
</div>
)}
}
Just change
const customers = [ 'Guacamole', 'Beef', 'Bean' ];
to
this.customers = [ 'Guacamole', 'Beef', 'Bean' ];
You are defining the customers variable as a const inside the constructor.
This variable will live while this method is executing, then it is gone.
You have to do something like this.customers, this way, the variable will be a property of the instance of your component, available in other methods. You can use both this.state as suggests by #kkangil, or just this.customers. The difference is that React keeps track of state in other to tigger re-rendering.
class App extends React.Component {
constructor(props){
super(props);
this.customers = [ 'Guacamole', 'Beef', 'Bean' ];
}
// ...
}
Try to use React state
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
customers =['Guacamole', 'Beef', 'Bean'];
}
}
render() {
return (
<div>
1) DataGrid
<Api customers={this.state.customers} />
</div>
);
}
}
export default App;
class Api extends React.Component {
render() {
return (
<div>
{this.props.customers}
</div>
)
}
}
Or you can use just variable without state
class App extends React.Component {
customers = ['Guacamole', 'Beef', 'Bean'];
constructor(props) {
super(props);
}
render() {
return (
<div>
1) DataGrid
<Api customers={this.customers} />
</div>
);
}
}
export default App;
class Api extends React.Component {
render() {
return (
<div>
{this.props.customers}
</div>
)
}
}

React: Function in Parent Component not receiving data from Child Component

I'm working on a project using React where I need to update the state of the Parent Component with the Child Component's input. I did console.log() my way through each function in the chain and found that the fetchText() function in my parent component didn't receive the text
Here's what my parent component looks like
class AppComponent extends React.Component{
constructor(props){
super(props);
this.state = { markdownText: `` };
this.fetchText = this.fetchText.bind(this);
}
fetchText(text){
this.setState({ markdownText: text });
console.log(text);
}
render(){
return(
<div id="app-grid">
<h1>Markdown Viewer</h1>
<MarkDownComponent userInput={this.fetchText} />
<PreviewComponent />
</div>
);
}
}
My Child Component looks like this
class MarkDownComponent extends React.Component{
constructor(props){
super(props);
this.state = { text: ``};
this.getInput = this.getInput.bind(this);
this.sendInput = this.sendInput.bind(this);
}
getInput(event){
this.setState({ text: event.target.value });
this.sendInput();
}
sendInput(){
this.props.userInput = this.state.text;
//console.log(this.props.userInput);
}
render(){
return(
<div id="markdown-component">
<textarea id="editor" rows="16" onChange={this.getInput}></textarea>
</div>
);
}
}
When console.log()ing this.props.userInput in the Child Component I get the value back as I type. So that indicates the value is making it to the property, but why isn't it updating in the parent component?
Few things to note here:
you cannot change the value of props, it is passed to the component through it parent
this.props.userInput = this.state.text;
this won't work.
So, to make fetchData of parent get the text from textarea you should do like this
<textarea id="editor" rows="16" onChange={this.props.userInput}></textarea>
and in parent component :
fetchText(event){
console.log(event.target.value)
this.setState({ markdownText: event.target.value });
}
you don't require functions like getInput and sendInput to send data to the parent component.
The issue is you are assigning state value to a function which is not correct.
this.props.userInput = this.state.text; // this is incorrect
//Right one
class MarkDownComponent extends React.Component{
constructor(props){
super(props);
this.state = { text: ``};
this.getInput = this.getInput.bind(this);
this.sendInput = this.sendInput.bind(this);
}
getInput(event){
this.setState({ text: event.target.value });
this.sendInput();
}
sendInput(){
this.props.userInput(this.state.text);
//console.log(this.props.userInput);
}
render(){
return(
<div id="markdown-component">
<textarea id="editor" rows="16" onChange={this.getInput}></textarea>
</div>
);
}
}
You can directly call this.props.userInput function in getInput function:
class MarkDownComponent extends React.Component{
constructor(props){
super(props);
this.state = { text: ``};
this.getInput = this.getInput.bind(this);
}
getInput(event){
this.props.userInput(event.target.value);
}
render(){
return(
<div id="markdown-component">
<textarea id="editor" rows="16" onChange={this.getInput}></textarea>
</div>
);
}
}
ES6 way:
class MarkDownComponent extends React.Component{
constructor(props){
super(props);
this.state = { text: ``};
}
getInput = (event) => {
this.props.userInput(this.state.text);
}
render(){
return(
<div id="markdown-component">
<textarea id="editor" rows="16" onChange={this.getInput}></textarea>
</div>
);
}
}
As told in the comments, there is no need to assign a state to your function. Also, if your desire is to change the text with a Child and nothing more you don't need a state in your Child. Don't use state if it is not necessary.
class AppComponent extends React.Component {
constructor(props) {
super(props);
this.state = { markdownText: "" };
this.fetchText = this.fetchText.bind(this);
}
fetchText(e) {
this.setState({ markdownText: e.target.value});
}
render() {
return (
<div id="app-grid">
<h1>Markdown Viewer</h1>
Value is now: {this.state.markdownText}
<MarkDownComponent userInput={this.fetchText} />
</div>
);
}
}
const MarkDownComponent = ( props ) => {
return (
<div id="markdown-component">
<textarea id="editor" rows="16" onChange={props.userInput}></textarea>
</div>
)
}
ReactDOM.render(<AppComponent />, document.getElementById("root"));
<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="root"></div>

Triggering a parent function from child using props

I am trying to do something simple: I want my child component to trigger a function found in my parent component, and I understand the right way is using props.
In the following Codepen you can find an example:
https://codepen.io/akmur/pen/MvXGEG
Basically what I want to achieve is to print "hey" to console.
This is my code:
class Form extends React.Component {
constructor(props){
super(props);
}
onClickAdd(){
this.props.addItem();
}
render(){
return(
<div>
<button onClick={this.onClickAdd}>Add</button>
</div>
)
}
}
class App extends React.Component {
constructor(props){
super(props);
}
addItem(){
console.log('hey');
}
render() {
return (
<div>
<Form addItem={this.addItem} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
Thanks for your help!
You don't need the onClickAdd function. Just call this.props.addItem directly onClick (notice, no parens) that you passed down.
class Form extends React.Component {
constructor(props){
super(props);
}
render(){
return(
<div>
<button onClick={this.props.addItem}>Add</button>
</div>
)
}
}
class App extends React.Component {
constructor(props){
super(props);
}
addItem(){
console.log('hey');
}
render() {
return (
<div>
<Form addItem={this.addItem} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));

Child prop value not updated on Window , but i can see it get updated in console

I dont know what i am doing wrong in this code, the prop value 'number' is not updating on front end , although in the console logs it value does get increament.
import React from 'react';
import { render } from 'react-dom';
class Parent extends React.Component{
constructor(props){
super(props);
this.number=0;
this.changeValue=this.changeValue.bind(this);
}
changeValue(){
console.log('-------------this.number',this.number);
this.number=this.number+1;
}
render(){
return(
<div>
<Child callMe={this.changeValue} increaseNo={this.number}></Child>
</div>
)
}
}
class Child extends React.Component{
render(){
return(
<div>
<button onClick={this.props.callMe}>CLick Me</button>
<h1>{this.props.increaseNo}</h1>
</div>
)
}
}
render(<Parent/> , document.getElementById('root'));
You have to store this.number inside the component state, the component will only be re-rendered if its state changes or it receives new props.
class Parent extends React.Component{
constructor(props){
super(props);
this.state = {
number: 0
}
this.changeValue=this.changeValue.bind(this);
}
changeValue(){
this.setState({number: this.state.number + 1});
}
render(){
return(
<div>
<Child callMe={this.changeValue} increaseNo={this.state.number}></Child>
</div>
)
}
}
class Child extends React.Component{
render(){
return(
<div>
<button onClick={this.props.callMe}>CLick Me</button>
<h1>{this.props.increaseNo}</h1>
</div>
)
}
}
jsfiddle

Resources