I'm follow the steps of this dependencie:
http://jossmac.github.io/react-images/
And it isn't work. No picture showing and there is showing an error message:
index.js:2178 Warning: Failed prop type: The prop onClose is marked
as required in Lightbox, but its value is undefined
Here is my code:
import React, { Component } from "react";
import Lightbox from "react-images";
const URL_INTERIORES = "http://localhost:3001/interiores";
const LIGHTBOX_IMAGE_SET = [
{
src: "/images/int_02.jpg",
caption: "A forest",
// As an array
srcSet: ["/images/int_02.jpg", "/images/int_02.jpg"]
},
{
src: "/images/int_02.jpg",
// As a string
srcSet: "/images/int_02.jpg 1024w, /images/int_02.jpg 800w, /images/int_02.jpg 500w, /images/int_02.jpg 320w"
}
];
class Interiores extends Component {
render() {
const { open } = this.state;
return (
<div>
<div>
<Lightbox
images={LIGHTBOX_IMAGE_SET}
isOpen={this.state.lightboxIsOpen}
onClickPrev={this.gotoPrevLightboxImage}
onClickNext={this.gotoNextLightboxImage}
onClose={this.closeLightbox}
/>
</div>
</div>
);
}
}
export default Interiores;
Does anybody know how to solve it? Tahnk you
Consider adding all the missing handlers & state in your class:
class Interiores extends Component {
state = {
lightboxIsOpen: false
}
gotoPrevLightboxImage() {
// Add the logic here
}
gotoNextLightboxImage() {
// Add the logic here
}
closeLightbox(e) {
// Add the logic here
}
render() {
const { lightboxIsOpen } = this.state;
return (
<div>
<Lightbox
images={LIGHTBOX_IMAGE_SET}
isOpen={lightboxIsOpen}
onClickPrev={() => this.gotoPrevLightboxImage()}
onClickNext={() => this.gotoNextLightboxImage()}
onClose={e => this.closeLightbox(e)}
/>
</div>
);
}
}
Related
Hi i want to create a dropDown in react with each item having an icon. As i tried react-select but its not showing the icon ,and also the selected value .When i remove value prop from react-select component than the label is showing. I want to create the dropdown like the this.
//USerInfo.js
import React from "react";
import { connect } from "react-redux";
import FontAwesome from "react-fontawesome";
import Select from "react-select";
import { setPresence } from "../../ducks/user";
import "./UserInfo.css";
class UserInfo extends React.Component {
// constructor(props) {
// super(props);
// this.state = {
// currentPresence: "available",
// };
// }
presenceOpts = [
{ value: "available", label: "Available" },
{ value: "dnd", label: "Busy" },
{ value: "away", label: "Away" },
];
setPresenceFun(presence) {
this.props.setPresence(presence);
}
renderPresenceOption(option) {
return (
<div className="presenceOption">
<FontAwesome name="circle" className={"presenceIcon " + option.value} />
{option.label}
</div>
);
}
renderPresenceValue(presence) {
return (
<div className="currentPresence">
<FontAwesome
name="circle"
className={"presenceIcon " + presence.value}
/>
</div>
);
}
render() {
return (
<div className="UserInfo">
{this.props.client.authenticated && (
<div className="authenticated">
<div className="user">
<div className="presenceControl">
<Select
name="presence"
value={this.props.user.presence.value}
options={this.presenceOpts}
onChange={this.setPresenceFun.bind(this)}
clearable={false}
optionRenderer={this.renderPresenceOption}
valueRenderer={this.renderPresenceValue}
/>
</div>
<div className="username">
<p>{this.props.client.jid.local}</p>
</div>
</div>
</div>
)}
</div>
);
}
}
const mapStateToProps = (state, props) => ({
client: state.client,
user: state.user,
});
const mapDispatchToProps = (dispatch, props) => {
return {
setPresence: (presence) => dispatch(setPresence(presence)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(UserInfo);
You can customize the option for dropdown
This may assist you in resolving the custom styling issue with react select.
https://codesandbox.io/s/react-select-add-custom-option-forked-u1iee?file=/src/index.js
I'm building a react application, and on my HomePage, I have the component 'CategoriesList'.
When I'm on the HomePage, the 'Categories List' works well, but when I navigated to ProductDetails page with react-router-dom, I found this error:
"NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node."
'CategoriesList' uses Flickty. I tried to remove Flickity, and... Works well. But I need to use Flickity.
Can anyone help me?
CategoryList Component:
const CategoryList = ({list, popupOpen, refreshProductList}) => {
return (
<Container>
<Slider
options={{
cellAlign: 'center',
draggable: true,
groupCells: true,
contain: false,
pageDots: false,
}}
style={ popupOpen ? ({opacity: 0.05}) : null}
>
{list.map((category, index) => (
<Category key={index}>{category}</Category>
))}
</Slider>
</Container>
);
}
Flickty Slider Component:
import Flickity from 'flickity';
import 'flickity/dist/flickity.min.css';
export default class Slider extends Component {
constructor(props) {
super(props);
this.state = {
flickityReady: false,
};
this.refreshFlickity = this.refreshFlickity.bind(this);
}
componentDidMount() {
this.flickity = new Flickity(this.flickityNode, this.props.options || {});
this.setState({
flickityReady: true,
});
}
refreshFlickity() {
this.flickity.reloadCells();
this.flickity.resize();
this.flickity.updateDraggable();
}
componentWillUnmount() {
this.flickity.destroy();
}
componentDidUpdate(prevProps, prevState) {
const flickityDidBecomeActive = !prevState.flickityReady && this.state.flickityReady;
const childrenDidChange = prevProps.children.length !== this.props.children.length;
if (flickityDidBecomeActive || childrenDidChange) {
this.refreshFlickity();
}
}
renderPortal() {
if (!this.flickityNode) {
return null;
}
const mountNode = this.flickityNode.querySelector('.flickity-slider');
if (mountNode) {
return ReactDOM.createPortal(this.props.children, mountNode);
}
}
render() {
return [
<div style={this.props.style} className={'test'} key="flickityBase" ref={node => (this.flickityNode = node)} />,
this.renderPortal(),
].filter(Boolean);
}
}
If you want to use Flickity along with React instead of creating your own component, I highly recommend using react-flickity-component. It's also easy to use:
Tip: if you use wrapAround option in Flickity set
disableImagesLoaded prop ture (default is false).
import Flickity from 'react-flickity-component'
const flickityOptions = {
autoPlay: 4000,
wrapAround: true
}
function Carousel() {
return (
<Flickity
disableImagesLoaded
options={flickityOptions} // Takes flickity options {}
>
<img src="/images/placeholder.png"/>
<img src="/images/placeholder.png"/>
<img src="/images/placeholder.png"/>
</Flickity>
)
}
I have a data structure like this {key: [array of object]}. I want to render each element in array of object using nested for loop like this:
for each entry(k, v) in map:
for each element in array v:
display html data
I am using react version 16.
I tried this in JSX:
class Positions extends React.Component {
renderPosition(position) {
var expiry = position["ExpiryDay"] + "-" + position["ExpiryMonth"] + "-" + position["ExpiryYear"];
console.log(expiry);
return (<label>{expiry}</label>);
}
render() {
return (
<div>
{this.props.positionsGrouped.forEach(function(positions) {
return (
<div>
{positions.map(function(position) {
return (
<div>
{this.renderPosition(position)}
</div>
);
}.bind(this))}
</div>
);
}.bind(this))}
</div>
);
}
}
Here is the JS that it compiles to:
class Positions extends React.Component {
renderPosition(position) {
var expiry = position["ExpiryDay"] + "-" + position["ExpiryMonth"] + "-" + position["ExpiryYear"];
console.log(expiry);
return React.createElement(
"label",
null,
expiry
);
}
render() {
return React.createElement(
"div",
null,
this.props.positionsGrouped.forEach(function (positions) {
return React.createElement(
"div",
null,
positions.map(function (position) {
return React.createElement(
"div",
null,
this.renderPosition(position)
);
}.bind(this))
);
}.bind(this))
);
}
}
However I don't see anything being rendered except for the top most div. Here is the rendered html:
<div id="app">
<div></div>
</div>
Here is what I see in react developer tools:
<App>
<Positions>
<div></div>
</Positions>
</App>
I don't see any errors in the console. I expected at least three nested divs to be rendered however I only see one so it sounds like something is wrong at the level of the first for loop. But, I do see my expiry variable being printed to console properly so I know renderPosition is getting called with the correct data.
Does anyone know what I am doing wrong? I'm new to react and sorry for any typos. Thanks in advance.
this.props.positionsGrouped.forEach would return undefined. I mean it wouldn't return anything. So nothing gets rendered.
Just change your component code like this
import React from "react";
class Positions extends React.Component {
constructor(props) {
super(props);
this.renderPosition = this.renderPosition.bind(this);
}
renderPosition(position) {
var expiry = position["name"] + "-" + position["title"];
console.log(expiry);
return <label>{expiry}</label>;
}
render() {
const { positionsGrouped } = this.props;
return (
<div>
{positionsGrouped.map(positions => {
const keys = Object.keys(positions);
return (
<div>
{positions[keys[0]].map(position => {
return <div>{this.renderPosition(position)}</div>;
})}
</div>
);
})}
</div>
);
}
}
export default Positions;
Inside your parent file
import React from "react";
import ReactDOM from "react-dom";
import Position from "./test";
import "./styles.css";
function App() {
var positionGroup = [
{
a: [
{
name: "hello",
title: "sdfd"
},
{
name: "hello",
title: "sdfd"
},
{
name: "hello",
title: "sdfd"
}
]
},
{
b: [
{
name: "hello",
title: "sdfd"
},
{
name: "hello",
title: "sdfd"
},
{
name: "hello",
title: "sdfd"
}
]
}
];
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Position positionsGrouped={positionGroup} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
The return value of forEach is undefined no matter what you return in callback function. use map instead.
class Positions extends React.Component {
getExpiry(position) {
return `${position.ExpiryDay}-${position.ExpiryMonth}-${position.ExpiryYear}`;
}
render() {
return (
<div>
{this.props.positionsGrouped.map(positions => (
<div>
{positions.map((position) => (
<div>
<label>{this.getExpiry(position)}</label>
</div>
))}
</div>
))}
</div>
);
}
}
I changed your code a little to make it more concise.
I'm trying to build a photo gallery in React. So far I have an App component and a Photo component. The details for my images lives in the App components state, and I want to pass the images down to the Photo component. So far, so good.
However, when I try to assign the <img /> tag the appropriate source using the image props, it doesn't work. I'm doing this by <img src={ this.props.images.src } />. When I log it to the console, the value is undefined.
What's going on?
Code for the App component:
import React, { Component } from 'react';
import Photo from './components/Photo';
import images from './data/images';
import './App.css';
import './css/Photo.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
images: images,
visible: false,
modalClass: 'photo-modal-invisible'
};
}
handleClick(index) {
const isVisible = this.state.visible;
if(isVisible === false) {
this.setState({ visible: true, visibleClass: 'photo-modal-visible', activeImage: images[index] });
} else {
this.setState({ visible: false, visibleClass: 'photo-modal-invisible' });
}
}
render() {
return (
<div className="App">
<React.Fragment>
<div className="photo-container">
{
this.state.images.map((image, index) =>
<Photo
images={ this.state.images }
visible={ this.state.visible }
modalClass={ this.state.modalClass }
/>
)
}
</div>
</React.Fragment>
</div>
);
}
}
export default App;
Code for the Photo component:
import React, { Component } from 'react';
import './../css/Photo.css';
class Photo extends Component {
constructor(props) {
super(props);
}
render() {
return(
<img src={ this.props.images.src } />
);
}
}
export default Photo;
Image data:
export default [{
title: 'Mountain Road',
photographer: 'Emma Ayers',
alt: 'Mountain Road',
src: '/assets/images/image1.png'
}, {
title: 'Fall Forest',
photographer: 'Emma Ayers',
alt: 'Fall Forest',
src: '/assets/images/image2.png'
}, {
title: 'Flower Bridge',
photographer: 'Emma Ayers',
alt: 'Flower Bridge',
src: '/assets/images/image3.png'
}, {
title: 'Dry River',
photographer: 'Emma Ayers',
alt: 'Dry River',
src: '/assets/images/image4.png'
}, {
title: 'Moony Mountains',
photographer: 'Emma Ayers',
alt: 'Moony Mountains',
src: '/assets/images/image5.png'
}, {
title: 'Snowy Mountains',
photographer: 'Emma Ayers',
alt: 'Snowy Mountains',
src: '/assets/images/image6.png'
}
];
The problem lies within your map method, you are passing in the whole array (this.state.images) that you are attempting to map over. You can think of map as a functional for loop, so for each image you loop over, you are returning a <Photo /> and each instance of that loop is one of your objects that you defined within image data file.
this.state.images.map((image, index) => (
<Photo
image={image} // the fix
visible={this.state.visible}
modalClass={this.state.modalClass}
/>
)
and then in your Photo component
<img src={this.props.image.src} />
You should just pass one image to Photo component
<React.Fragment>
<div className="photo-container">
{
this.state.images.map((image, index) =>
<Photo
image={ image }
visible={ this.state.visible }
modalClass={ this.state.modalClass }
/>
)
}
</div>
</React.Fragment>
You don't need to make photo as stateful component. stateless functional component is enough for displaying just view.
const Photo (props) => (
<img src={ props.image.src } />
);
}
}
export default Photo;
app component:
import React, { Component } from 'react';
import Photo from './components/Photo';
import images from './data/images';
import './App.css';
import './css/Photo.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
images: images,
visible: false,
modalClass: 'photo-modal-invisible'
};
}
handleClick = (index) => {
const isVisible = this.state.visible;
if(isVisible === false) {
this.setState({ visible: true, visibleClass: 'photo-modal-visible', activeImage: images[index] });
} else {
this.setState({ visible: false, visibleClass: 'photo-modal-invisible' });
}
}
render() {
return (
<div className="App">
<React.Fragment>
<div className="photo-container">
{
this.state.images.map((image, index) =>
<Photo
images={image}
visible={this.state.visible}
modalClass={this.state.modalClass}
onClick={(index) => this.handleClick(index)}
/>
)
}
</div>
</React.Fragment>
</div>
);
}
}
export default App;
photo component:
import React, { Component } from 'react';
import './../css/Photo.css';
class Photo extends Component {
constructor(props) {
super(props);
}
render() {
return(
<img src={ this.props.images.src alt={this.props.images.alt}} />
);
}
}
export default Photo;
Here problem was image map function.. While passing the map function argument you are passing the direct state of image array here. So map works as in loop with image array object.
Here for active image, please share the use case so that I can give you better way to handle it.
I'm still new to React.
I'm making a guessing game. On page load, everything loads properly (on Chrome and Safari, at least). The cat buttons are assigned a random number and when clicked, they send the corresponding value to the game logic. When the target number is met or exceeded, the target number resets.
That's what I want, but I also want the buttons to get new values. I want the Buttons component to reload and assign the buttons new values. I've tried using the updating methods found here: https://reactjs.org/docs/react-component.html#updating. I don't know what to do next.
App.js
import React, { Component } from 'react';
import './App.css';
import Buttons from "./components/Buttons/Buttons";
class App extends Component {
targetNumber = (min, max) => {
const targetNum = Math.floor(Math.random()*(max-min+1)+min);
console.log(`Target number = ${targetNum}`);
return targetNum
};
state = {
targetNumber: this.targetNumber(19, 120),
currentValue: 0,
gamesWon: 0,
};
handleClick = (event) => {
event.preventDefault();
const currentValue = this.state.currentValue;
const newValue = parseInt(event.target.getAttribute("value"));
this.setState(
{currentValue: currentValue + newValue}
)
// console.log(newValue);
}
componentDidUpdate() {
if (this.state.currentValue === this.state.targetNumber) {
this.setState(
{
targetNumber: this.targetNumber(19, 120),
currentValue: 0,
gamesWon: this.state.gamesWon + 1
}
)
}
else {
if (this.state.currentValue >= this.state.targetNumber) {
this.setState(
{
targetNumber: this.targetNumber(19, 120),
currentValue: 0,
gamesWon: this.state.gamesWon,
}
);
}
}
}
render() {
return (
<div className="App">
<img src={require("./images/frame.png")} alt="frame" id="instructFrame" />
<div className="resultsDiv">
<div className="targetNumber">
Target number = {this.state.targetNumber}
</div>
<div className="currentValue">
Current value = {this.state.currentValue}
</div>
<div className="gamesWon">
Games won = {this.state.gamesWon}
</div>
</div>
<div className="buttonGrid">
<Buttons
onClick={this.handleClick}
/>
</div>
</div>
);
}
}
export default App;
Buttons.js
import React, { Component } from "react";
import Button from "../Button/Button";
import black from "../Button/images/black_cat.png";
import brown from "../Button/images/brown_cat.png";
import gray from "../Button/images/gray_cat.png";
import yellow from "../Button/images/yellow_cat.png";
class Buttons extends Component {
generateNumber = (min, max) => {
const rndNumBtn = Math.floor(Math.random()*(max-min+1)+min);
console.log(rndNumBtn);
return rndNumBtn
};
state = {
buttons: [
{
id: "black",
src: black,
alt: "blackBtn",
value: this.generateNumber(1, 12)
},
{
id: "brown",
src: brown,
alt: "brownBtn",
value: this.generateNumber(1, 12)
},
{
id: "gray",
src: gray,
alt: "grayBtn",
value: this.generateNumber(1, 12)
},
{
id: "yellow",
src: yellow,
alt: "yellowBtn",
value: this.generateNumber(1, 12)
}
]
};
render() {
return (
<div>
{this.state.buttons.map(button => {
return (
<Button
className={button.id}
key={button.id}
src={button.src}
alt={button.alt}
value={button.value}
onClick={this.props.onClick.bind(this)}
/>
)
})}
</div>
)
}
}
export default Buttons;
Here's the GitHub repo. https://github.com/irene-rojas/numberguess-react
You can add a key to the Button component linking to the variable targetNumber. That way, React would rerender the Button whenever targetNumber changes.
<div className="buttonGrid">
<Buttons
key={this.state.targetNumber}
onClick={this.handleClick}
/>
</div>