I have the problem when I use the Reactjs, I'm really new to Reactjs, so maybe it's a easy problem:
class Product extends Component{
handleUpVote() {
this.props.onVote(this.props.id)
}
render(){
return(
<div className='item'>
<div className='middle aligned content'>
<div className='header'>
<a onClick={this.handleUpVote}>
<i className='large caret up icon'></i>
</a>
{this.props.votes}
</div>
</div>
</div>
)
}
}
class ProductList extends Component {
handleProductUpVote(prductId){
console.log(productId +' was upvoted')
}
render() {
const products1 = Data.sort((a,b) => (
b.votes-a.votes
));
const products=products1.map((product) =>{
return (
<div className='ui items'>
<Product
key={'product-'+product.id}
id={product.id}
onVote={this.handleProductUpVote}
/>
</div>
)})
return (
<div className='ui items'>
{products}
</div>
)
}}
export default ProductList;
At this line I am getting the error and i cant understand why:
this.props.onVote(this.props.id)
Forget binding this.
You need to pass the ID as a parameter to your click handler function.
Something like this:
class Product extends Component{
handleUpVote(id) {
this.props.onVote(id)
}
...
<Product
key={'product-'+product.id}
id={product.id}
onVote={() => this.handleProductUpVote(product.id)}
/>
}
Related
I am trying to render a child component with images from local folder, but I don't know how to do it.
So I have a const array with details about several projects. Each of the project has its own folder with images. The project name is equal folder name with images
Parent component
import { myProjects } from '../lib/Projects'; //its array with projects
export default class Parent extends Component {
render() {
// function for images
function importAll(r) {
return r.keys().map(r);
}
const projectA = importAll(require.context('../../assets/images/projectA', false, /\.(png|jpe?g|svg)$/));
const projects = myProjects.map((project, i) =>
<Child id={i} key={i} project={project} />)
return (
<div className="main-container">
{projects}
</div>
)
}
}
Child component
export default class Child extends Component {
render() {
const { project } = this.props;
return (
<div className="item">
<div className="desc">
<div className="item-name">
<p>{project.name}</p>
</div>
<div className="item-description">
<p>{project.description}</p>
</div>
<div className="item-tools">
<p>{project.tools}</p>
</div>
</div>
// this part works well
// How to make below part work?
<div className="image-block">
<div className="item-image-first">
<img src={project.name[0]} alt=""/>
</div>
<div className="item-images">
{project.name ? project.name.map((image, index) => {
return (
<div className="image-block-small" key={index}>
<ModalImage
small={image}
large={image}
alt=""
hideDownload={true}
hideZoom={true}
className="modal-image"
/>
</div>
)
})
: null }
</div>
</div>
</div>
)
}
}
Maybe there is a way to add an extra array here?
const projects = myProjects.map((project, i) =>
<Child id={i} key={i} project={project} />)
Any suggestion?
I am using the Context API to manage state in a small app. I get the response OK, the Consumer has it, so I map through it and want to pass down data from it to a Product Card component through props. And the Product Card renders absolutely nothing. I get no errors whatsoever. Can anyone help me out please? Here is the code of parent component:
import Pagination from "./Pagination";
import { Consumer } from "../context";
export default class Browse extends Component {
render() {
return (
<Consumer>
{value => {
const { search } = value;
return (
<ProductsGrid>
{search.map(beer => (
<ProductCard
key={beer.id}
beerId={beer.id}
beerName={beer.name}
beerTagline={beer.tagline}
beerAbv={beer.abv}
firstBrewed={beer.first_brewed}
imageUrl={beer.image_url}
/>
))}
</ProductsGrid>
);
}}
</Consumer>
);
}
}`````
and here is the Product Card component:
```export default class ProductCard extends React.Component {
render() {
return (
<div className="product-card">
<div className="product-card-inner">
<div className="product-info-container">
<h1 className="beer-name">{this.props.beerName}</h1>
<p className="beer-type">{this.props.beerTagline}</p>
<p className="beer-alcohol">{this.props.beerAbv}%</p>
<p className="first-brewed">
First brewed: {this.props.firstBrewed}
</p>
</div>
<div className="beer-image-container">
<img src={this.props.imageUrl} alt="beer" />
</div>
<div className="price-container">
<h1>£ 3.50</h1>
</div>
<div className="button-container">
<div className="quantity-container">
<p className="minus-sign"> - </p>
<p className="qty-number"> 0 </p>
<p className="plus-sign"> + </p>
</div>
<div className="add-container">
<IoIosCart />
<p>Add</p>
</div>
</div>
</div>
</div>
);
}
}```
I failed to call two funtion in componentDidMount.When I clicked bangla its change and when i clicke english its change but during routing it stays only english so i wanted to set the state in componentDidMount,but it only invoke one funtion.if click the bangla it set bangla but when i change the routing its remain the same lang. so how can i set it.
import React, { Component } from 'react';
import { connect } from "react-redux";
import {setLanguage} from "../../actions";
import { Link } from "react-router-dom";
class MenuComp extends Component {
constructor(props){
super(props);
this.setLang = this.setLang.bind(this);
this.state= {
"maintitle": {
"titlelist": [
{"title1":"Timetable"},
{"title2":"Ticket Prices"},
{"title3":"About Us"}
]
}
};
}
setLang(lang){
this.props.setLanguage(lang);
this.props.history.push('/menu');
}
changeLanguage = () => {
this.setState({
"maintitle": {
"titlelist": [
{"title1":"সময়সূচী"},
{"title2":"টিকেটর মূল্য"},
{"title3":"আমাদের সম্পর্কে"}
]
}
});
};
changeLang = () => {
this.setState({
"maintitle": {
"titlelist": [
{"title1":"Timetable"},
{"title2":"Ticket Prices"},
{"title3":"About Us"}
]
}
});
};
componentDidMount() {
this.changeLanguage();
this.changeLang();
}
render() {
return (
<div className="Menu">
<div className="menu-header">
<div className="container-fluid p-0">
<div className="row m-0">
<div className="col-md-4 p-0 d-flex justify-content-end">
<div className="align-self-center">
<a className="lang" onClick={() => { this.setLang('bn'); this.changeLanguage(); }}>Bangla</a> |
<a className="lang l-active" onClick={() => { this.setLang('en'); this.changeLang(); }}>English</a>
</div>
</div>
</div>
</div>
</div>
<main className="navigation">
<div className="container-fluid p-0">
<div className="row m-0">
<div className="col-md-4 pl-0">
<Link to="/timetable" className="lang">
<div className="card-content">
<h6 className="card-title">{
this.state.maintitle.titlelist.map((title, i)=>{
return (<p key={i}>{title.title1} </p>)
})
}</h6>
</div>
</Link>
</div>
<div className="col-md-4 pl-0">
<Link to="/ticketprice" className="lang">
<div className="card-content">
<h6 className="card-title">{
this.state.maintitle.titlelist.map((title, i)=>{
return (<p key={i}>{title.title2} </p>)
})
}</h6>
</div>
</Link>
</div>
</Link>
</div>
</div>
</div>
</main>
</div>
);
}
}
function mapStateToProps(state){
return {
lang: state.lang.lang
}
}
const Menu = connect(mapStateToProps, {setLanguage})(withRouter(MenuComp));
export default Menu;
It's an asynchronous problem. So, the setState method runs asynchronously. This makes reading this.state right after calling setState() a potential pitfall.
So, the lines inside your componentDidMount method get executed, however, you can't predict which one of them will finish before the other.
Now, I don't completely understand what you're trying to achieve, but instead, use componentDidUpdate or a setState callback (setState(updater, callback)): something like this:
this.setState((state, props)=> ({
"maintitle": {
"titlelist": [
{"title1":"সময়সূচী"},
{"title2":"টিকেটর মূল্য"},
{"title3":"আমাদের সম্পর্কে"}
]
}
}), ()=> {// do what you want next!})
// (this could be inside your componentDidMount!
If that didn't help, please let me know!
I want to use the same function showHide to show/hide each element within the parent.
When I press the button all 3 blocks reacts and hide or show.
How can I extend the function to work individualy for each div?
This is a localhost test project so I can't provide any link unfortunately.
Here you can see the final result
import React, { Component } from 'react';
class Homepage extends Component {
constructor( props ){
super( props )
this.state = {show : true};
this.showHide = this.showHide.bind(this)
}
render() {
return (
<section id="content">
<div className="top-content">
<div className="container">
<h1>React</h1>
<h2>A JavaScript library for building user interfaces</h2>
</div>
</div>
<div className="container">
<div>
<div>
<h3>Declarative</h3>
<button onClick={this.showHide} className="button-primary btn">{this.changeName()}</button>
{ this.state.show &&
<div>
<p>text</p>
<p>text</p>
</div>
}
</div>
<div>
<h3>Component-Based</h3>
<button onClick={this.showHide} className="button-primary btn">{this.changeName()}</button>
{ this.state.show &&
<div>
<p>text</p>
<p>text</p>
</div>
}
</div>
<div>
<h3>Learn Once, Write Anywhere</h3>
<button onClick={this.showHide} className="button-primary btn">{this.changeName()}</button>
{ this.state.show &&
<div>
<p>text</p>
<p>text</p>
</div>
}
</div>
</div>
</div>
</section>
);
}
changeName(){
let text = "text "
text += this.state.show === true ? "hide" : "show";
return text;
}
showHide(){
const { show } = this.state;
this.setState( { show : !show})
}
}
export default Homepage;
The problem here is that your using the same state variable for each div (this.state.show).
If you want to have the divs behave differently, they each need their own state.
import React, { Component } from 'react';
class Homepage extends Component {
constructor( props ){
super( props )
this.state = {show: [true, true,true]};
}
render() {
return (
<section id="content">
<div className="top-content">
<div className="container">
<h1>React</h1>
<h2>A JavaScript library for building user interfaces</h2>
</div>
</div>
<div className="container">
<div>
<div>
<h3>Declarative</h3>
<button onClick={()->this.showHide(0)} className="button-primary btn">{this.changeName()}</button>
{ this.state.show[0] &&
<div>
<p>text</p>
<p>text</p>
</div>
}
</div>
<div>
<h3>Component-Based</h3>
<button onClick={()->this.showHide(1)} className="button-primary btn">{this.changeName()}</button>
{ this.state.show[1] &&
<div>
<p>text</p>
<p>text</p>
</div>
}
</div>
<div>
<h3>Learn Once, Write Anywhere</h3>
<button onClick={()->this.showHide(2)} className="button-primary btn">{this.changeName()}</button>
{ this.state.show[2] &&
<div>
<p>text</p>
<p>text</p>
</div>
}
</div>
</div>
</div>
</section>
);
}
changeName(){
let text = "text "
text += this.state.show === true ? "hide" : "show";
return text;
}
showHide(num){
this.setState((prevState) => {
const newItems = [...prevState.show];
newItems[num] = !newItems[num];
return {show: newItems};
});
}
}
export default Homepage;
Obviously there are nicer ways of doing this, but this is just an example to show the separation of states.
Can't test it right now, but shouldn't be far off.
UPDATE: #Lasitha ty for the much nicer edit!
I am a novice in ReactJS. I want to print out the image and text in the state object, but I do not know why it does not work when the system does not show any error. The following is my code
import React, { Component } from 'react';
class Asgn6 extends Component {
constructor(){
super();
this.state={
content:[
{srcImg:"../img/1.png", text:"Black"},
{srcImg:"../img/2.png", text:"Blue"},
{srcImg:"../img/3.png", text:"Green"}
]
}
}
add=() => {
}
render() {
return (
<div>
{this.state.content.map((obj, index)=> {
return (
<div key={index}>
<img src={require(obj.srcImg)} alt={obj.text}/>
<p>{obj.text}</p>
</div>
);
})}
);
<button onClick={this.add}>Add</button>
</div>
);
}
}
export default Asgn6;
The first rule you need to remember about automatic semicolon insertion is to keep whatever you return on the same line after return keyword. Otherwise this
return
<div>
<img src={require(obj.srcImg)} alt={obj.text}/>
<p key={index}>{obj.text}</p>
</div>
is equivalent to
return;
<div>
<img src={require(obj.srcImg)} alt={obj.text}/>
<p key={index}>{obj.text}</p>
</div>
Note, how semicolon is inserted after return.
Simple fix can be
return <div>
<img src={require(obj.srcImg)} alt={obj.text}/>
<p key={index}>{obj.text}</p>
</div>
or use parenthesis to group your returns:
return (
<div>
<img src={require(obj.srcImg)} alt={obj.text}/>
<p key={index}>{obj.text}</p>
</div>
)
<img src={obj.srcImg} alt={obj.text}/>
just do this.