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>
);
}
}
Related
I am trying to change colour of text in h1 tag when I click button. I am calling change colour function but when onclick it executes at that time it is showing error in the inside statement [ this.styling_text.color="black" ]
import React,{Component} from 'react';
class InlineDynamic extends Component{
changeColor = () =>{
this.styling_text.color="black"
};
render(){
const styling_text = {color:"red"};
return(
<div>
<h1 style={styling_text} >Change My Colour !! on click</h1>
<button onClick={this.changeColor}>click me</button>
</div>
);
}
}
export default InlineDynamic;
If you want to update the color property, add styling_text object to the component state:
class InlineDynamic extends React.Component {
constructor() {
super();
this.state = {
styling_text: { color: "red" },
};
}
changeColor = () => {
this.setState({ styling_text: { color: "black" } });
};
render() {
const {styling_text} = this.state;
return (
<div>
<h1 style={styling_text}>Change My Colour !! on click</h1>
<button onClick={this.changeColor}>click me</button>
</div>
);
}
}
EDIT:
Other solution is to use React.createRef :
class InlineDynamic extends React.Component {
constructor() {
super();
this.styling_text = React.createRef(null);
}
componentDidMount() {
this.styling_text.current.style.color = "black";
}
changeColor = () => {
this.styling_text.current.style.color = "red";
};
render() {
return (
<div>
<h1 ref={this.styling_text}>Change My Colour !! on click</h1>
<button onClick={this.changeColor}>click me</button>
</div>
);
}
}
Declare styling_text outside of render
class InlineDynamic extends Component{
changeColor = () =>{
this.styling_text.color="black"
};
styling_text = {color:"red"};
render(){
return(
<div>
<h1 style={styling_text} >Change My Colour !! on click</h1>
<button onClick={this.changeColor}>click me</button>
</div>
);
}
}
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>
);
}
}
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;
I have two child components. The first child is an image and the second child is a search input. When I type something in the input field, I want the image to hide itself. The passing of data from the second child to the parent goes well. But the first child still appears...
Parent:
class Main extends React.Component {
constructor() {
super();
this.state = {
displayValue: 'block'
};
}
hideImage = () => () => {
alert('You pressed a key, now the apple should be gone')
this.setState ({
displayValue: 'none'
});
};
render() {
return (
<div>
<Image />
<Search hideImage={this.hideImage()}/>
</div>
);
}
}
ReactDOM.render(<Main />, document.getElementById('root'));
First Child:
export default class Image extends Component {
render() {
return (
<div>
<img style={{display : this.props.displayValue}} src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTAxoq2YSBjoS0Lo3-zfqghoyNzZ9jHxoOc5xuFBoopMtKP6n4B"></img>
</div>
)
}
}
Second Child:
export default class Search extends Component {
render() {
return (
<div>
<input onInput={this.props.hideImage} placeholder="Search someting"></input>
</div>
)
}
}
You have to pass the displayValue state into your Image component as a prop. Also you have to pass the hideImage function without initializing it using the two brackets. The below code should work for you.
class Main extends React.Component {
constructor() {
super();
this.state = {
displayValue: 'block'
};
}
hideImage = () => () => {
alert('You pressed a key, now the apple should be gone')
this.setState ({
displayValue: 'none'
});
};
render() {
return (
<div>
<Image displayValue={this.state.displayValue}/>
<Search hideImage={this.hideImage}/>
</div>
);
}
}
You just had a couple of typos.
class Image extends React.Component {
render() {
return (
<div>
<img
style={{ display: this.props.displayValue }}
src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTAxoq2YSBjoS0Lo3-zfqghoyNzZ9jHxoOc5xuFBoopMtKP6n4B"
alt="altprop"
/>
</div>
);
}
}
// Second Child:
class Search extends React.Component {
render() {
return (
<div>
<input onInput={this.props.hideImage} placeholder="Search someting" />
</div>
);
}
}
class Main extends React.Component {
constructor() {
super();
this.state = {
displayValue: "block"
};
}
hideImage(e) {
e.preventDefault();
alert("You pressed a key, now the apple should be gone");
this.setState({
displayValue: "none"
});
};
render() {
return (
<div>
<Image displayValue={this.state.displayValue}/>
<Search hideImage={this.hideImage.bind(this)} />
</div>
);
}
}
Call your Image component like this
<Image displayValue={this.state.displayValue} />
It should then already work, but here is a shorter way to write your code.
// First Child:
const Image = ({displayValue}) => <div>
<img alt='' style={{display : displayValue}} src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTAxoq2YSBjoS0Lo3-zfqghoyNzZ9jHxoOc5xuFBoopMtKP6n4B"></img>
</div>
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>