i am implementing an image slideshow kind of thing in react using npm package - react-simple-image-slider.
implementation->
export default function Home(){
const images = [
{ url: "images/1.jpg" },
{ url: "images/2.jpg" },
{ url: "images/3.jpg" },
];
const open = true;
<SimpleImageSlider
width={`${open ? 896 : 880}`}
height={`${open ? 430 : 440}`}
images={images}
showBullets={true}
showNavs={true}
/>
}
i am trying to change height, width based on a variable. but this doesnt load anything. page is empty. am i missing something. please help.
you can try passing in numeric values directly and conditionally set them like follow code, I think it will work as expected.
<SimpleImageSlider
width={open ? 896 : 880}
height={open ? 430 : 440}
images={images}
showBullets={true}
showNavs={true}
/>
Related
I want to make an image slider in my application using the 'react-simple-image-slider
' package. But it only show the first image only..
In my firestore, my imageUrl is stored like this:
In the documentation of the package, it shows that the 'images' should be stored in this format:
The website of this package:
https://www.npmjs.com/package/react-simple-image-slider
Then, in my application, I have fetched the data and store the imageUrl into the 'image' and pass it into 'SimpleImageSlider' to use it.
const ProductPage = ({ collection, match }) => {
const { items } = collection;
const image = [{url: items[match.params.itemId - 1].imageUrl}];
console.log(image);
return (
<div className='collection-page'>
<SimpleImageSlider
width={500}
height={500}
images={image}
showBullets={true}
showNavs={true}
/>
<div className='items'>
{items[match.params.itemId - 1].name}
</div>
</div>
)
};
However, the application only show the first image in the slider:
I have console.log(image) and I thought I already store the 3 imageURL into the array, but I have no idea why it only displays the first one? Is it something wrong on the method I store the 'image' and how can I convert it to fit the structure that the documentation need from the data I fetched from database?
Your array is of format url: [], when the docs say each object in the array should be of format { url: "" }. So, ensure your array looks like this:
[
{ url: "https://..." },
{ url: "https://..." },
{ url: "https://..." },
]
This should work as it will assign an object to each item
const ProductPage = ({ collection, match }) => {
let { items } = collection;
let image = []
useEffect(()=>{
items.map(item=>image.push({url: item.imageUrl}))
},[])
console.log(image);
return (
<div className='collection-page'>
{image.length && <SimpleImageSlider
width={500}
height={500}
images={image}
showBullets={true}
showNavs={true}
/>
}
<div className='items'>
{items[match.params.itemId - 1].name}
</div>
</div>
)
};
I'm new to React Native, so I understand I have alot to learn.
I'm creating a custom class component here:
import React, { Component, useState } from 'react';
import {View,Text,StyleSheet,TextInput, Button} from 'react-native';
class Square extends React.Component{
constructor(pos,text,won,save){
this.state = {
pos : 0,
text : 'EDIT',
won : false,
save : false,
};
}
setPos = (pos) =>{
this.setState(pos)
}
getPos = () => {
return (this.pos);
}
setText=(text)=>{
this.setState(text)
}
getText=()=>{
return (this.text);
}
setWon=(won)=>{
this.setState(won)
}
getWon=()=>{
return (this.won);
}
setSave=(save)=>{
this.setState(save)
}
getSave=()=>{
return (this.save);
}
};
export default Square;
Then I want to create an array of those objects in a different component and display a piece of information from each object.
import {View, Text, StyleSheet, Button, Alert} from 'react-native';
import Square from '../components/Square';
const NewGameScreen = () => {
let arrSquare = [];
for (let i = 0; i < 25; i++){
arrSquare.push({
THIS IS WHERE I'M HAVING TROUBLE
});
}
console.log(arrSquare[0].getPos)
return(
<View style = {styles.screen}>
<View style = {styles.row}>
<Text>{arrSquare[0].getPos}</Text>
</View>
</View>
)
};
However from the above code I'm sure it's clear I'm missing something. I would have expected to use something like Square[i].setPos(i); but that throws errors. The console log also gives 'undefined' so that makes me think I haven't declared something or haven't declared it properly. Thanks in advance.
well the way I would go about this is to have a simple array of json object something like this:
let squareArr = [{
id: 0,
pos : 0,
text : 'EDIT',
won : false,
save : false,
},
{
id: 1,
pos : 0,
text : 'EDIT',
won : false,
save : false,
},
{
id: 2,
pos : 0,
text : 'EDIT',
won : false,
save : false,
}
]
then you can do the the read and the edit.
to display a position:
in your render method you can do this:
<View style = {styles.screen}>
<View style = {styles.row}>
squareArr.map((square) => <Text>{square.pos}</Text>)
</View>
</View>
to edit a position:
if you want to change a value in your JSON then just use the object index as a way to indicate which object you wanna change. For example want to change the pos of the second object then I would do this:
squareArr[1].pos = 3
I am not quite sure what is the whole project is to give you to give you the best solution but i hope this helps..
feel free to ask if you have any questions
I can't figure out how to dynamically set the width of a component.
I am using the component 'vue-burger-menu' -> https://github.com/mbj36/vue-burger-menu.
To set the width one needs to set the prop width to a number. As per the example below:
<Slide
ref="slideToggle"
disable-esc
class="slideToggle"
width="470"
right
:burger-icon="false"
:cross-icon="false"
disable-outside-click
>
It then sets a helper class - bm-menu width to the width. I have spent quite a while trying to figure out how to either set the prop's attribute dynamically or dynamically update the style.
For example I tried setting: this.$refs.slideToggle.$attrs.width = 1000 to no avail.
I can't bind a style to the bm-menu class as it's not visible.
How do I set the width so on the click of a button it changes (as per the button example below)?
Thanks for your help!
setDrawWidth() {
this.lineDrawWidth = "200px";
}
You just need binding which uses : before props:
<Slide
ref="slideToggle"
disable-esc
class="slideToggle"
:width="width"
right
:burger-icon="false"
:cross-icon="false"
disable-outside-click
>
And then in your data in js part:
export default {
data:() => ({ width: '470' }),
}
Now you just need to change width variable. For example:
export default {
data:() => ({ width: '470' }),
methods:{
changeWidth(){
this.width = '1000';
}
}
}
You can read more about binding variables from the doc: Vue Props
Listen on window width event:
data: () => ({
width: 470
})
created() {
window.addEventListener("resize", this.changeWidth);
},
destroyed() {
window.removeEventListener("resize", this.changeWidth);
},
methods: {
changeWidth(e) {
const screenWidth = window.innerWidth;
this.width = screenWidth
}
}
and set width in Slide component:
<Slide
ref="slideToggle"
disable-esc
class="slideToggle"
:width="width"
right
:burger-icon="false"
:cross-icon="false"
disable-outside-click
>
I'm working in react and basically I want to make an button with tooltip, right now I'm making tooltip. I'm changing css display property in order to make it visible or not during mouse enter and leave. But there is an error and I don't know what to do...
Here is my code:
import React from 'react';
import ReactDOM from 'react-dom';
import Style from 'style-it';
var Ink = require('react-ink');
import FontIcon from '../FontIcon/FontIcon';
var IconButton = React.createClass({
getInitialState() {
return {
iconStyle: "",
style: "",
cursorPos: {},
};
},
extend(obj, src) {
Object.keys(src).forEach(function(key) { obj[key] = src[key]; });
return obj;
},
Tooltip(props) {
var style = {};
if (this.tooltipDisplay) {
style.display = "block";
} else if (!this.tooltipDisplay) {
style.display = "none";
};
return <div className="tooltip" style={style}>{_props.tooltip}</div>;
},
showTooltip(){
this.tooltipDisplay = true;
},
removeTooltip(){
this.tooltipDisplay = false;
},
render() {
var _props = this.props,
tooltip = this.Tooltip,
opts,
tooltipDisplay = false,
disabled = false,
rippleOpacity,
outterStyleMy = {
border: "none",
outline: "none",
padding: "8px 10px",
"background-color": "red",
"border-radius": 100 + "%",
cursor: "pointer",
},
iconStyleMy = {
"font-size": 12 + "px",
"text-decoration": "none",
"text-align": "center",
display: 'flex',
'justify-content': 'center',
'align-items': 'center',
},
rippleStyle = {
color: "rgba(0,0,0,0.5)",
};
if (_props.disabled || _props.disableTouchRipple) {
rippleStyle.opacity = 0;
};
this.setState({
iconStyle: _props.iconStyle
});
this.setState({
style: _props.style
});
if (_props.disabled) {
disabled = true;
};
if (this.state.labelStyle) {
iconStyleMy = this.state.iconStyle;
};
if (this.state.style) {
outterStyleMy = this.state.style;
};
if (_props.href) {
opts.href = _props.href;
};
var buttonStyle = this.extend(outterStyleMy, iconStyleMy);
return(
<Style>
{`
.IconButton{
position: relative;
}
.IconButton:disabled{
color: ${_props.disabledColor};
}
.btnhref{
text-decoration: none;
}
`}
<a {...opts} className="btnhref" >
<tooltip text={this.props.tooltip} position={this.options} />
<button ref="button" className={"IconButton" + _props.className} disabled={disabled} style={buttonStyle}
onMouseEnter={this.showTooltip} onMouseLeave={this.removeTooltip} >
<Ink background={true} style={rippleStyle} opacity={rippleOpacity} />
<FontIcon className={_props.iconClassName}/>
</button>
</a>
</Style>
);
}
});
ReactDOM.render(
<IconButton href="" className="" iconStyle="" style="" iconClassName="face" disabled="" disableTouchRipple="" tooltip="aaaaa" />,
document.getElementById('app')
);
In console I'm getting this error:
Uncaught RangeError: Maximum call stack size exceeded
at defineRefPropWarningGetter (App.js:1053)
at Object.ReactElement.createElement (App.js:1220)
at Object.createElement (App.js:3329)
at Constructor.render (App.js:43403)
at App.js:15952
at measureLifeCyclePerf (App.js:15233)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (App.js:15951)
at ReactCompositeComponentWrapper._renderValidatedComponent (App.js:15978)
at ReactCompositeComponentWrapper._updateRenderedComponent (App.js:15902)
at ReactCompositeComponentWrapper._performComponentUpdate (App.js:15880)
I can't find out what's wrong. I know it might be something about calling a function which in turn calls another function. But I can't see anything like this in my code and I'm not sure if it's all about it. Thanks for help :)
The problem is you are calling setState from inside your render function. State changes should only happen as a result of something changing: user clicked on a button, the browser window was resized, a picture was taken, etc.
Never ever ever ever update the state while rendering (repeat that last sentence 20 times and never forget it).
Here is the problem code:
render () {
...
this.setState({
iconStyle: _props.iconStyle
});
this.setState({
style: _props.style
});
...
}
The above code would cause an infinite loop of sorts because setState causes render to be called. Since iconStyle and style are props, and props cannot change, you should use those props to build your initial state.
getInitialState() {
return {
iconStyle: this.props.iconStyle,
style: this.props.style,
cursorPos: {},
};
}
Later, if someone clicks a button and you want the iconStyle to change, you would create a click handler which updates your state:
handleClick () {
this.setState({
iconStyle: 'clicked'
});
}
This would cause your component to be rerendered and the new state would be reflected.
Think of your "state" as someone cooking and we are going to take photographs of them cooking. The initial state is "eggs cracked: no, flour poured: no, veggies chopped: no", and you take a picture of this state. Then the chef does something - cracks the eggs. The state has now changed, and you take a picture of it. Then she cuts the veggies. Again, the state has changed and you take a picture.
Each photograph in the analogy represents your "render" function - a snapshot of the "state" at a particular point in time. If every time you took a photograph the flour got poured, well we would have to take another picture because the flour was just poured. Taking another picture would cause more flour to get poured so we'd have to take another picture. Eventually you'd fill the kitchen to the ceiling with a celiac's nightmare and suffocate everybody in the room. You'd also run out of film or hard disk space on your camera.
Thanks to #RyanWheale I noticed my mistake.
In my render function I was returning a button element which called a function which changed a certain state. The returned button looked like this:
<button onclick={this.edit()} className="button-primary">Edit</button>
And my edit function changes some state and looks like this:
edit: function () {
this.setState({editing: true});
}
So, I my mistake is that I, accidentally, typed the parenthesis after this.edit. So, when the button element was being rendered, the edit function was actually called and chaos happened. Now, when I wrote
<button onclick={this.edit} className="button-primary">Edit</button>
instead of
<button onclick={this.edit()} className="button-primary">Edit</button>
it worked flawlessly.
I hope I help someone save hours of his precious life.
Cheers :)
I faced the same problem, I had installed "reactime" extension and that extension caused me this problem. Removing that extension from my chrome, solved the issue.
I got 'Maximum call stack size exceeded', and similar errors because of framer-motion API dependency, version bigger than 4.1.17 (today's version is 5.5.5). I don't figured out why yet.
For the same extensions also, got some weird errors like 'window.webkitStorageInfo' is deprecated, and similar bugs.
I had the same error in my SPFX project while running Gulp Serve. I deleted the newly added reference in my config.json file and it worked.
More details: https://fixingsharepoint.blogspot.com/2022/04/rangeerror-maximum-call-stack-size.html
I'm currently creating a custom React component in Meteor for adding images to a list (and later uploading them). However when I try to delete images from the list, always the last element is removed from the GUI. Initially I thought this was just a simple case of using the wrong index for deletion, but it turned out to be more than that.
This is what my ImageList component currently looks like:
import React from 'react';
import Dropzone from 'react-dropzone';
import cloneDeep from 'lodash.clonedeep';
import { ImageItem } from './image-item.js';
export class ImagesList extends React.Component {
constructor(props) {
super(props);
this.values = this.props.images || [];
this.onDrop = this.onDrop.bind(this);
this.addImages = this.addImages.bind(this);
this.deleteImage = this.deleteImage.bind(this);
this.imageChanged = this.imageChanged.bind(this);
}
onDrop(files) {
this.addImages(files);
}
onDropRejected() {
alert('Invalid file type');
}
addImages(files) {
files.forEach(file => {
this.values.push({
title: '',
description: '',
url: file.preview,
file,
});
});
this.forceUpdate();
}
deleteImage(index) {
console.log('index to delete', index);
console.log('images pre-delete', cloneDeep(this.values)); // deep-copy because logging is async
this.values.splice(index, 1);
console.log('images post-delete', cloneDeep(this.values)); // deep-copy because logging is async
this.forceUpdate();
}
imageChanged(index, image) {
this.values[index] = image;
this.forceUpdate();
}
render() {
console.log('--------RENDER--------');
return (
<div className="image-list">
<div className="list-group">
{this.values.length === 0 ?
<div className="list-group-item">
No images
</div>
:
this.values.map((image, index) => {
console.log('rendering image', image);
return (
<ImageItem
key={index}
image={image}
onDelete={() => { this.deleteImage(index); }}
onChange={(item) => { this.imageChanged(index, item); }}
deletable={true}
/>
);
})
}
</div>
<Dropzone
multiple={true}
onDrop={this.onDrop}
onDropRejected={this.onDropRejected}
className="dropzone"
activeClassName="dropzone-accept"
rejectStyle={this.rejectStyle}
accept={'image/*'}
>
<span>Drop files here</span>
</Dropzone>
</div>
);
}
}
The ImagesList component can be initialized with some values (for the sake of debugging), which it uses during rendering. For example:
<ImagesList images={[
{ title: 'Image 1', description: 'Image 1 description', url: 'http://cssdeck.com/uploads/media/items/3/3yiC6Yq.jpg' },
{ title: 'Image 2', description: 'Image 2 description', url: 'http://cssdeck.com/uploads/media/items/4/40Ly3VB.jpg' },
{ title: 'Image 3', description: 'Image 3 description', url: 'http://cssdeck.com/uploads/media/items/0/00kih8g.jpg' },
]}/>
ImagesList renders an ImageItem component for each image. This is what this component looks like:
import React from 'react';
import { RIEInput, RIETextArea } from 'riek';
export class ImageItem extends React.Component {
constructor(props) {
super(props);
this.placeholder = {
title: 'Title',
description: 'Description',
};
this.value = this.props.image;
}
render() {
return (
<div className="list-group-item">
<div className="text-content">
<h4>
<RIEInput
className="description"
value={this.value.title.length <= 0 ?
this.placeholder.title : this.value.title}
change={(item) => {
this.value.title = item.value;
this.props.onChange(this.value);
}}
validate={(value) => value.length >= 1}
classEditing="form-control"
propName="value"
/>
</h4>
<span>
<RIETextArea
className="description"
value={this.value.description.length <= 0 ?
this.placeholder.description : this.value.description}
change={(item) => {
this.value.description = item.value;
this.props.onChange(this.value);
}}
validate={(value) => value.length >= 1}
classEditing="form-control"
propName="value"
rows="2"
/>
</span>
</div>
<img className="thumb img-responsive"
style={{width: '20%' }}
src={this.value.url}
alt="Image"
data-action="zoom"
/>
{this.props.deletable ?
<div className="delete-btn">
<span onClick={this.props.onDelete}>
×
</span>
</div>
:
undefined }
</div>
);
}
}
Let's say I have three images, image A, B and C, and I want to delete image B. After pressing the delete button, image C will disappear from the GUI instead.
Inside the deleteImage() function of ImagesList, I am logging the index that is to be deleted and also log the values before and after the deletion. The index that is logged is correct, in this case that is index 1. Before the deletion the values are images A, B and C. After deletion the values are images A and C, as they should be.
I decided to do some logging inside the render() function of ImagesList as well. Unfortunately this also logs the correct values A and C, but A and B are actually rendered.
I have also tried to use the React state for this component instead of storing it in a local variable in conjunction with forceUpdate().
Another thing I have tried is to use the React Developer Tools plugin for Chrome. The Devtools also show the correct values, but the GUI still does not, as shown in this screenshot.
I'm currently out of ideas on what to try, any help would be appreciated!
Using the snippets I provided, you should be able to create a Meteor project and reproduce this bug.
With MasterAM's suggestion I managed to find two different solutions.
A.) Using componentWillUpdate()
The this.value variable is set only once namely in the constructor of the ImageItem component. To ensure that changes are properly delegated, you have to update this.value inside the componentWillUpdate() function. Something like:
componentWillUpdate(nextProps, nextState) {
this.value = nextProps.image;
}
B.) Using the property directly
This is definitely the more proper solution. Here we get rid of the local variable this.value inside the constructor of the ImageItem component.
Inside the render() function you replace this.value with this.props.image. Now without having to use the componentWillUpdate() function, everything works as expected.