Passing data from parent to child reactjs? - 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>
)
}
}

Related

Function in class can't call outer function

function Welcome(props) {
console.log("Welcome Back");
}
class App extends React.Component {
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
<Welcome />
}
render(){
return (
<div>
<button onClick={this.handleClick}>CLICK HERE </button>
</div>
);
}
}
Why function handleClick can't call outer function Welcome? is there any solution to this?
To call that function, you should do as follows:
function welcome(props) {
console.log("Welcome Back");
}
class App extends React.Component {
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
}
render(){
return (
<div>
<button onClick={this.handleClick}>CLICK HERE </button>
</div>
);
}
}
Notice that I've lowercased your Welcome function since Pacalcased function names should be reserved for React Components as a general naming convention.
If your intention is to have Welcome be a React component, then it should return some JSX and then you should render that out inside of the render function of your class component:
function Welcome(props) {
return (<div>Welcome Back!</div>
}
class App extends React.Component {
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
welcome()
}
render(){
return (
<div>
<Welcome />
<button onClick={this.handleClick}>CLICK HERE </button>
</div>
);
}
}
If you'd like to hide your welcome message until you click the button, you can use state:
function Welcome(props) {
return (<div>Welcome Back!</div>
}
class App extends React.Component {
constructor(props){
super(props);
this.state = {
showWelcomeMessage: false
}
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
this.setState({showWelcomeMessage: true})
}
render(){
return (
<div>
{this.state.showWelcomeMessage ? <Welcome /> : null}
<button onClick={this.handleClick}>CLICK HERE </button>
</div>
);
}
}
In your example changing <Welcome /> to Welcome() is enough. But you should use camelCase to define functions. But here is the refactored version.
import React from "react";
const welcome = () => {
console.log("Welcome Back");
};
export default function App() {
const handleClick = () => {
welcome();
};
return (
<div>
<button onClick={handleClick}>CLICK HERE </button>
</div>
);
}
Just change the calling of the outer function "Welcome", because it is not a Component:
handleClick(){
Welcome()
}

How to pass props in React

I am new to React and I am finding it difficult to pass props from one component to another.
This is the first component
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
// show:true
};
}
counter = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div className="">
<div>{this.state.count}</div>
</div>
);
}
}
and this is the second
export default class Button extends React.Component {
render() {
return (
<div className="">
<App />
<button onClick={this.counter}>Click me</button>
</div>
);
}
}
How do I make the counter count by passing props in the apps component
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
// show:true
};
}
counter = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div className="">
<div>{this.state.count}</div>
<Button counter={this.counter} />
</div>
);
}
}
export default class Button extends React.Component {
render() {
return (
<div className="">
<button onClick={this.props.counter}>Click me</button>
</div>
);
}
}

How do I get onClick to work in my nested React Component?

UPDATE: My code checked out just fine. The issue was that a stopPropagation() was called in a separate Javascript library that prevented my onClicks from working.
--
I have a "MenuLink" react component in which I've added an onClick listener to an 'a' tag. The "MenuLink" component is imported from a "MenuItem" component which is imported from a "MainMenu" component (see below).
When I click on link generated from MenuLink, nothing happens. No errors, no nothing. I would expect to see "handleClick" in my console and for the link to be prevented from executing.
MenuLink.js
class MenuLink extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = props.link;
}
handleClick(e) {
console.log("handleClick");
e.preventDefault();
}
render() {
const link = this.state;
return (
<a
href={link.alias}
onClick={this.handleClick}
>
{link.title}
</a>
);
}
}
export default MenuLink;
MenuItem.js
import MenuLink from './MenuLink.js';
class MenuItem extends React.Component {
constructor(props) {
super(props);
this.state = props.item;
}
render(key) {
const item = this.state;
return(
<li
key={key}
>
<MenuLink
link={item}
/>
</li>
);
}
}
export default MenuItem;
MainMenu.js
import MenuItem from '../components/MenuItem.js';
class MainMenu extends React.Component {
state = {
menu: []
}
render() {
return(
<ul className="menu">
{this.state.menu.map(function(menuItem, i) {
return(
<MenuItem key={i} item={menuItem} />
)
})}
</ul>
);
}
componentDidMount() {
fetch('/api/menu_items/main')
.then(res => res.json())
.then((data) => {
this.setState({ menu: data })
})
.catch(console.log)
}
}
export default MainMenu;
The below snippet shows that it does work as expected. No changes were made.
class MenuLink extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = props.link;
}
handleClick(e) {
console.log("handleClick");
e.preventDefault();
}
render() {
const link = this.state;
return (
<a
href={link.alias}
onClick={this.handleClick}
>
{link.title}
</a>
);
}
}
class MenuItem extends React.Component {
constructor(props) {
super(props);
this.state = props.item;
}
render(key) {
const item = this.state;
console.log(key) // Undefined. Don't do this
return(
<li
key={key}
>
<MenuLink
link={item}
/>
</li>
);
}
}
class MainMenu extends React.Component {
state = {
menu: [{
alias: 'test',
title: 'test'
},
{
alias: 'test2',
title: 'test2'
}]
}
render() {
return(
<ul className="menu">
{this.state.menu.map(function(menuItem, i) {
return(
<MenuItem key={i} item={menuItem} />
)
})}
</ul>
);
}
}
ReactDOM.render(<MainMenu />, 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"/>
Please check this example:
import React from "react";
class MenuLink extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
// this.state = props.link;
this.state = {
link: {alias: "http://www.google.com", title: 'Google'}
}
}
handleClick(e) {
console.log("handleClick");
e.preventDefault();
}
render() {
const link = this.state.link;
return (
<div>
<a
href={link.alias}
onClick={this.handleClick}
>
{link.title}
</a>
</div>
);
}
}
export default MenuLink;
This approach should work
class MenuLink extends React.Component {
constructor(props) {
super(props);
//this.handleClick = this.handleClick.bind(this);
this.state = props.link;
}
handleClick = e => {
console.log("handleClick");
e.preventDefault();
}
render() {
const link = this.state;
return (
<a
href={link.alias}
onClick={this.handleClick}
>
{link.title}
</a>
);
}
}
export default MenuLink;

Binding a props function

I have two React Components, Gallery & Image. The Image Component uses a Gallery function as props.
Can I do the call in the render without an arrow function?
Image component:
class Image extends React.Component {
constructor(props) {
super(props);
this.state = {
filter: 'none',
};
}
render() {
return (
<div>
<button className="image-icon" onClick={() => this.props.handleClone(this.props.i)} />
</div>
);
}
}
Gallery component:
class Gallery extends React.Component {
constructor(props) {
super(props);
this.handleClone = this.handleClone.bind(this);
this.state = {
images: [],
};
}
handleClone(i) {
var newImages = this.state.images;
newImages = newImages.slice(0, i + 1).concat(newImages.slice(i));
this.setState({
images: newImages,
});
}
render() {
return (
<div>
<div className="gallery-root">
{this.state.images.map((dto, i) => {
return <Image key={'image-' + dto.id + '-' + i} i={i} handleClone={this.handleClone} />;
})}
</div>
</div>
);
}
}
Thanks.
class Image extends React.Component {
constructor(props) {
super(props);
this.state = {
filter: 'none'
};
}
handleClick = () => {
this.props.handleClone(this.props.i);
};
render() {
return (
<div>
<button className="image-icon" onClick={this.handleClick} />
</div>
);
}
}

React js - Uncaught TypeError: Cannot read property of undefined

I have a problem (
There are my components:
class Main extends Component {
constructor(props) {
super(props);
this.state = {
total: 0
};
this.totalFuns = this.totalFuns.bind(this);
}
totalFuns(event){
this.setState({total: event})
}
render() {
return (
<main>
<Item data_items={data} data_cnt={this.totalFuns} />
</main>
);
}
}
export default Main;
then Item component:
class Item extends Component {
constructor(props){
super(props);
this.skuChange = this.skuChange.bind(this);
}
skuChange(event) {
this.props.data_cnt(event)
}
render() {
return (
<section className="item" data-index={this.props.data_index}>
<Select values={this.props.data_items} onChange={this.skuChange}/>
</section>
);
}
}
export default Item;
then Select component
class Select extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.props.onChange(event.target.value);
this.setState({value: event.target.label});
}
render() {
var options = this.props.values;
var options_list = options.map(function(obj,i){
return (
<option value={i} key={i} label={obj.label} />
)
});
return (
<select value={this.state.value} onChange={this.handleChange}>
{options_list}
</select>
);
}
}
export default Select;
In console show: Uncaught TypeError: Cannot read property 'totalFuns' of undefined. Without this fun my app work correct.. (
Why?
Your function is actually called totalFuns but you have totalFun.
So this line:
<Item data_items={data} data_cnt={this.totalFun} />
should be
<Item data_items={data} data_cnt={this.totalFuns} />
In your Select component, the state value was initially undefined and hence you were getting error. Also, the options can be selected based on value instead of label. See the working snippet below. Also I do not see data being present in the Main component
class Main extends React.Component {
constructor(props) {
super(props);
this.state = {
total: 0
};
this.totalFuns = this.totalFuns.bind(this);
}
totalFuns(event){
console.log(event);
this.setState({total: event})
}
render() {
var data = [{label: 1}, {label: 2}]
return (
<main>
<Item data_items={data} data_cnt={this.totalFuns} />
</main>
);
}
}
class Item extends React.Component {
constructor(props){
super(props);
this.skuChange = this.skuChange.bind(this);
}
skuChange(event) {
this.props.data_cnt(event)
}
render() {
return (
<section className="item" data-index={this.props.data_index}>
<Select values={this.props.data_items} onChange={this.skuChange}/>
</section>
);
}
}
class Select extends React.Component {
constructor(props) {
super(props);
this.state = {
value: ''
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.props.onChange(event.target.value);
this.setState({value: event.target.value});
}
render() {
var options = this.props.values;
var options_list = options.map(function(obj,i){
return (
<option value={obj.label} key={i} label={obj.label} />
)
});
return (
<select value={this.state.value} onChange={this.handleChange}>
{options_list}
</select>
);
}
}
ReactDOM.render(<Main/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="app"></div>

Resources