I try to use the event .isOpen does not update its status when I click on my popup.
Someone know why or know how to do ?
This is my code :
class Map extends React.Component {
constructor(props) {
super(props);
this.state = {
x: 0,
y: 0,
geojsonData: null,
geojsonData6: null,
}
}
initMap() {
//Declaration of the map
var valMarker = L.marker([this.state.y, this.state.x]).addTo(this.state.map)
.bindPopup('Hotel "Port de Calais"<br> 7 circuits à proximités.')
var valPopup = valMarker.getPopup()
if (valPopup.isOpen() === true) {
var myData = [this.state.geojsonData, this.state.geojsonData6]
L.geoJSON(myData).addTo(this.state.map)
}
}
componentDidMount() {
this.initData(2985).then((data) => {
this.setState({geojsonData: JSON.parse(data[0].geojson)})
});
//and more
this.initData(4661).then((data) => {
this.setState({geojsonData6: JSON.parse(data[0].geojson)})
this.initMap()
});
}
render() {
<Map />
return <div id="map" style={style} />;
}
}
I think, I need to do something in render(), but I don't find actually the solution.
Of course, when I do "marker.openPopup();" before the .isOpen(), the condition is true. But I want a action from the user?
Thanks !
Related
Here I am getting some problems with AliceCarousel to map my response to display its images in the gallery.
I wanted to display the respective types of images for each gallery.
I am generally following SO example .
Any help or suggestion here to make it possible?
Thanks is advance.
//Js
class KitchenService extends Component {
constructor(props) {
super(props);
this.state = {
currentIndex: 0,
responsive: { 1024: { items: 3 } },
galleryItems: this.galleryItems(),
services : this.props.resume,
...props,
ItemsServices:[]
}
}
static propTypes = {
getService: PropTypes.func.isRequired,
resume: PropTypes.object.isRequired,
auth: PropTypes.object.isRequired,
loading: PropTypes.object.isRequired
}
UNSAFE_componentWillReceiveProps(nextProps) {
if(nextProps.resume !== this.props.resume){
var services = this.props.resume.services;
this.setState({
ItemsServices: services
})
}
}
componentDidMount() {
this.props.getService();
}
slideTo = (i) => this.setState({ currentIndex: i })
onSlideChanged = (e) => this.setState({ currentIndex: e.item })
galleryItems = () => {
return this.state.ItemsServices.map((brand, i) => {
var checkImage = brand.length !== 0 && brand.service_name === "Office";
console.log(checkImage, "checkImage")
return (
<div key={`key-${i}`} className="card-img-top"><img src={brand.service_image_url} /></div>
)
})
};
render() {
const { responsive, currentIndex } = this.state
const items = this.galleryItems();
return(
<div>
<Grid className ="col-12 service-kitchen-gallery-grid" >
<div className="service-gallery-headline">
Kitchen
</div>
<AliceCarousel
dotsDisabled={true}
buttonsDisabled={true}
items={items}
responsive={responsive}
slideToIndex={currentIndex}
onSlideChanged={this.onSlideChanged}
/>
</Grid>
</div>
)
}
}
const mapStateToProps = (state) => ({
resume: state.resume,
});
export default connect(mapStateToProps, {getService }) (KitchenService);
//Error
TypeError: Cannot read property 'ItemsServices' of undefined
service API response
(console.log(services))
[
{
_id: "5f1971da18ba2b04704d65c2",
service_name: "Other",
service_image_url:
"https://res.cloudinary.com/tammycloudinary/image/upload/v1595503076/nou0knjbtkujxwjktang.png",
date: "2020-07-23T11:17:46.928Z",
__v: 0,
},
{
_id: "5f1971b218ba2b04704d65c1",
service_name: "Bedroom",
service_image_url:
"https://res.cloudinary.com/tammycloudinary/image/upload/v1595503036/kfiteeilh4doytio6gs8.png",
date: "2020-07-23T11:17:06.742Z",
__v: 0,
}
];
The issue is not coming from const items = this.galleryItems(); like I originally thought. It is coming from the constructor.
You are attempting to use the state object in order to build the initial state object. This obviously will not work.
constructor(props) {
super(props);
this.state = {
currentIndex: 0,
responsive: { 1024: { items: 3 } },
galleryItems: this.galleryItems(), // <-- Here is the problem
services : this.props.resume,
...props,
ItemsServices:[]
}
}
You attempt to initialize state by calling this.galleryItems. But that function relies on this.state already being declared. Since it has not been created yet (but is in the process of being declared), it is undefined and you get this error.
I don't think gallaryItems really belongs in state at all. It's generally not recommended to store JSX in state anyway. Instead just use the function like you have in the render to compute the JSX needed each render.
Another note: Don't use this.props in the constructor. Instead use the props that are passed in to the constructor.
Y0u can solve this with this solution as well with filter.
render() {
const { services, loading} = this.props.resume;
var checkImage = services.length === 0 ? [] : services.filter((item) => item.service_name === "Kitchen")
return(
<div>
<OwlCarousel className="owl-theme" loop margin={10} nav>
{checkImage.map((item, i) => (
<div className="col-xs-12 item" key={item._id} data-id={item._id} >
<img className="service-gallery-images" src={item.service_image_url} alt=""/>
</div>
))}
</OwlCarousel>
</div>
)
}
I have a problem with my code:
class Albs extends React.Component{
constructor(props){
super(props);
this.state = {
i: 0,
anh: this.props.hinhanh[this.state.i]
};
var hinhanh = ["1.png", "2.png", "3.png"];
this.state.i = this.state.i.bind(this);
}
nextPic(){
this.setState({i: this.state.i++});
}
backPic(){
this.setState({i: this.state.i--});
}
render(){
return(
<div>
<img src={this.state.anh}/>
<br/>
<button onClick={nextPic}>Next</button>
<button onClick={backPic}>Back</button>
</div>
)
}
}
ReactDOM.render(
<Albs/>,
document.getElementById('root')
);
In console it shows: Uncaught TypeError: Cannot read property 'i' of undefined. Reason please?
You need to bind the class this to your methods nextPic and backPic as you do with this.state.i (I don't see how it's necessary)
Or you could use this syntax
nextPic = () => {
this.setState({i: this.state.i++});
}
backPic = () => {
this.setState({i: this.state.i--});
}
There are lots of mistakes you made, look at my code and compare yours. Hope you can find the error.
class App extends Component {
constructor(props) {
super(props);
this.state = {
i: 0
};
var hinhanh = ["1.png", "2.png", "3.png"];
this.nextPic = this.nextPic.bind(this);
this.backPic = this.backPic.bind(this);
}
componentDidMount() {
this.setState({ anh: this.state.i});
}
nextPic() {
this.setState({ i: this.state.i++ });
console.log(this.state.i);
}
backPic() {
this.setState({ i: this.state.i-- });
console.log(this.state.i);
}
render(){
return(
<div>
<img src={this.state.anh}/>
<br/>
<button onClick={this.nextPic}>Next</button>
<button onClick={this.backPic}>Back</button>
</div>
)
}
}
You can define state property immediately into state like this this.state = { i: 0, j: this.state.i}, herejis undefined. So you need to use life cycle methodcomponentDidMounttosetState`.
You need to bind your functions, otherwise you need to use arrow function like this, nextPic = () => {//function defination}
I want to send my counter on my parent component but I have an error. I tried different code but none works.
I just want to send the counter and afterwards the score, if I can.
DuelTurn.JS
state = {
compteur: 0
}
constructor(props) {
super(props)
}
componentWillMount() {
this.setState({compteur: this.state.compteur++}, () => {
this.props.callback(this.state.compteur)
})
}
handleClick(step) {
if(step === true) {
console.log('gagné')
} else {
console.log('perdu')
}
}
render() {
return (
<div>
<div className="turn-player">Cest le tour de {this.props.pseudo} !</div>
<div className="text-left">
{this.props.data[0].pseudo}
<div>{this.props.firstScore}</div>
</div>
<div className="text-right">
{this.props.data[1].pseudo}
<div>{this.props.secondScore}</div>
</div>
<div className="clear"></div>
<div className="question"><div>Question :</div>La france a remporté la coupe du monde 98.</div>
<div onclick={this.handleClick(true)} className="true">Vrai</div>
<div onclick={this.handleClick(false)} className="false">Faux</div>
</div>
)
}
}
DuelGame.js
class DuelGame extends React.Component {
state = {
compteur: 0,
firstUser: this.props.dataUser[0].pseudo,
secondUser: this.props.dataUser[1].pseudo,
firstScore: 0,
secondScore: 0,
}
constructor(props) {
super(props)
}
receiveCallBack = (compteur) => {
this.setState({compteur})
console.log(compteur)
}
userTurn() {
if(this.state.compteur == 0 % 2) {
return <DuelTurn key={this.state.firstUser}
pseudo={this.state.firstUser}
firstScore={this.state.firstScore}
secondScore={this.state.secondScore}
compteur={this.state.compteur}
data={this.props.dataUser}
callback={this.receiveCallback}/>
} else {
return <DuelTurn
key={this.state.secondUser}
pseudo={this.state.secondUser}
firstScore={this.state.firstScore}
secondScore={this.state.secondScore}
compteur={this.state.compteur}
data={this.props.dataUser}
callback={this.receiveCallback}/>
}
}
render() {
return (
<div>{this.userTurn()}</div>
)
}
}
And my error is:
bundle.js:36630 Uncaught TypeError: _this2.props.callback is not a function
How to fix it?
Here is your issue, you have defined the function as receiveCallBack while you are calling this as receiveCallback (B,b).
other than that you are getting empty data in your props, I suggest you put an extra check before rendering data. So instead of this.props.dataUser[0] use this.props.dataUser && this.props.dataUser[0] and like wise for your this.props.dataUser[1] use this.props.dataUser && this.props.dataUser[1]
same goes for your this.props.data[0] and this.props.data[1] use conditional rendering there as well.
That should make it work
Here is a working version of your code
https://codesandbox.io/s/3196py0vqq
I'm trying to load items from JSON and toggle a dropdown div with description on click. While I can display elements sequentially (ex: loc1 & desc1, loc2 & desc2) on static divs I'm having trouble finding out how to render it properly when the second part (desc) is hidden and only shows when the loc div is clicked.
What would be the best way to map the result so it doesn't show as loc1 & loc2, desc1 & desc2 but as loc1 & desc1, loc2 & desc2?
Code:
var places = {
library: {
location: [
{
loc_name: "library1",
"desc": "desc1 : Modern and spacious building"
},
{
loc_name: "library2",
"desc": "desc2 : A cosy small building"
}
]
}
};
function contentClass(isShow) {
if (isShow) {
return "content";
}
return "content invisible";
}
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isShow: false };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(function (prevState) {
return { isShow: !prevState.isShow };
});
}
render() {
const libraries_desc = places.library.location.map((libr) =>
<div>
<p>{libr.desc}</p>
</div>
);
const lib_names = places.library.location.map((libr) =>
<div>
<p>{libr.loc_name}</p>
</div>
);
return (
<div>
<div className='control' onClick={this.handleClick}>
<h4>{lib_names}</h4>
<div className={contentClass(this.state.isShow)}>{libraries_desc}</div>
</div>
</div>
);
}
}
render((
<Toggle />
), document.getElementById('root'));
Current result:
library1
library2
desc1 : Modern and spacious building
desc 2 : A cosy small building
Desired Result:
library1
desc1 : Modern and spacious building (hidden but shown when clicked)
library2
desc 2 : A cosy small building (hidden but shown when clicked)
Codesandbox
I might try extracting a location into a separate component. By extracting it, each location is responsible for knowing its state. In your case, that means its visibility (controlled by this.state.isShow).
Here's how you could do it:
import React from 'react';
import { render } from 'react-dom';
var places = {
library: {
location: [
{
loc_name: "library1",
"desc": "Modern and spacious building"
},
{
loc_name: "library2",
"desc": "A cosy small building"
}
]
}
};
class Location extends React.Component {
constructor(props) {
super(props);
this.state = { isShow: false };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(function (prevState) {
return { isShow: !prevState.isShow };
});
}
contentClass(isShow) {
if (isShow) {
return "content";
}
return "content invisible";
}
render() {
return (
<div className='control' onClick={this.handleClick}>
<h4>{this.props.desc}</h4>
<div className={this.contentClass(this.state.isShow)}>{this.props.loc_name}</div>
</div>
)
}
}
class Toggle extends React.Component {
constructor(props) {
super(props);
}
render() {
const locations = places.library.location.map(location => {
return <Location {...location} />
})
return (
<div>
{locations}
</div>
);
}
}
render((
<Toggle />
), document.getElementById('root'));
Your Toggle Component should be like this.
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {
isShow: false,
id: -1, // initial value
};
}
handleClick = (id) => {
this.setState({
isShow: !this.state.isShow,
id: id
});
}
render() {
const { location } = places.library;
const { isShow, id } = this.state;
return (
<div className="control">
{location.map((libr, index) => (
<div key={index} onClick={() => { this.handleClick(index) }}>
<p>{libr.loc_name}</p>
{(isShow && (id === index)) && <p>{libr.desc}</p>}
</div>
))}
</div>
);
}
}
So when you click on the div element. A click event will be triggered called handleClick which will pass the index as a param to the function. which will set isShow to false or truth and vice versa along with the current element you want to show which will be selected through this.state.id. So everytime isShow is true and this.state.id matched index element of the array. Your description will show otherwise it will be hidden as you want.
So your desired result will be something like this.
library1
desc1 : Modern and spacious building (hidden but shown when clicked)
library2
desc 2 : A cosy small building (hidden but shown when clicked)
I'm building a component which proceeds according to the selections of the users. I have completed it successfully but facing some issues when trying to implement a back button to go back.
My code is like follows.
class ReportMainCat extends Component {
constructor(props) {
super(props);
this.state = {
postType: null,
}
this.changeType = this.changeType.bind(this);
this.report_next = this.report_next.bind(this);
};
report_next() {
if (this.state.postType == null) {
return <ReportFirst changeType={this.changeType}/>
}
else if (this.state.postType === 'sexual') {
return <ReportXContent changeType={this.changeType}/>
} else if (this.state.postType === 'selfharm') {
return <ReportThreatContent changeType={this.changeType}/>
}
}
changeType = (postType) => {
this.setState({postType})
this.setState({
showMainReportCats: false,
})
}
render() {
return (
<div className="top_of_overlay">
<div className="section_container text_align_center padding_10px">
<a className="">Report Category</a>
{this.report_next()}
</div>
</div>
)
}
}
I'm binding the postType value as follows.
class ReportXContent extends Component {
constructor(props) {
super(props);
this.state = {
postType: '',
}
};
textType(postType) {
this.props.changeType(postType);
}
render() {
return (
<div className="text_align_left">
<div>
<div className="width_100 margin_bottom10px">
<input type="checkbox" ref="nudity" onClick={this.textType.bind(this,'nudity')}/>
<a>Nudity or Pornography</a>
</div>
<div className="width_100 margin_bottom10px">
<input type="checkbox" ref="minor" onClick={this.textType.bind(this,'minor')}/>
<a>Includes Minors</a>
</div>
</div>
<ReportButtons/>
</div>
)
}
}
My back button
<div>
<button className="float_right margin_left5px" onClick={this.props.back_report}>Back</button>
</div>
So basically what i'm trying to do is this.
Ex: If the user selects postType as sexual it will return the ReportXContent component. How can i return to the first page when the user clicks the back button.
Thanks.
You could implement the back button click handler like this in the ReportMainCat component:
handleBackClick() {
this.setState({ postType: null });
}
, and that would show the ReportFirst view again.
If you don't want the first view, but the last view, simply change your changeType implementation to save lastPostType to state like this:
changeType = (postType) => {
this.setState({
lastPostType: this.state.postType,
postType,
showMainReportCats: false,
});
}
Edit
If you want full history of changes - let's say if you want to implement a full back button history - you can simply rename lastPostType to postTypeHistory and implement it like a stack (like the browser history is):
changeType = (postType) => {
this.setState({
postTypeHistory: [...this.state.postTypeHistory, this.state.postType],
postType,
showMainReportCats: false,
});
}
handleBackClick() {
const { postTypeHistory } = this.state;
const postType = postTypeHistory.pop();
this.setState({
postType,
postTypeHistory,
});
}