React - Parsing error: Unexpected token, expected ";" - javascript

I'm trying to call a method inside resize() when the screen width is less than or equal to 900, but I get the error Parsing error: Unexpected token, expected ";" how to fix this problem? https://ibb.co/cX0QxS1
https://ibb.co/bQSj1hq
import React, { Fragment } from 'react';
import less from "./css/lesson.module.css";
import "./css/activeLink.css";
import "./css/betaLesson.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { Navbar } from "../../../Navbar/Navbar";
import ReactHtmlParser from 'react-html-parser';
import * as Icon from 'react-bootstrap-icons';
import styled from "styled-components";
import { slide as Menu } from 'react-burger-menu'
import { NavbarMobile } from '../../../Navbar/Mobile_Navbar/NavbarMobile';
const NextPage = styled.button`
display: flex;
align-items: center;
font-family: 'Roboto';
font-weight: 500;
letter-spacing: 0.2px;
color: #ff7b77d9;
padding: 9px 22px;
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
font-size: 13px;
border: 1px solid #ff7b77d9;
border-radius: 2px;
`;
export class Lessons extends React.Component {
constructor(props) {
super(props);
this.state = {
indexDescription: 1,
listActiveIndex: 1,
sidebarMobile: true,
menuMobileIsOpen: false,
}
}
componentDidMount() {
window.addEventListener("resize", this.resize.bind(this));
this.resize();
}
resize() {
if (window.innerWidth > 900) {
this.setState({ sidebarMobile: true })
this.setState({ menuMobileIsOpen: false })
} else {
this.setState({ sidebarMobile: false })
}
}
hideMenu() {
this.setState({ sidebarMobile: false })
}
componentWillUnmount() {
window.removeEventListener("resize", this.resize.bind(this));
}
changeDescription(index) {
this.setState({ indexDescription: index, listActiveIndex: index })
}
nextPage() {
// next page
this.setState({ indexDescription: this.state.indexDescription + 1, listActiveIndex: this.state.indexDescription + 1 })
}
prevPage() {
// next page
this.setState({ indexDescription: this.state.indexDescription - 1, listActiveIndex: this.state.indexDescription - 1 })
}
showsidebarMobile = () => {
this.setState({ sidebarMobile: !this.state.sidebarMobile })
}
menuMobileIsOpen = () => {
this.setState({ menuMobileIsOpen: !this.state.menuMobileIsOpen })
}
HideMenuMobileIsOpen = () => {
this.setState({menuMobileIsOpen: false})
}
showSettings(event) {
event.preventDefault();
}
render() {
const listLessons = this.props.lesson.map((item, index) => {
// active link
const className = this.state.listActiveIndex === index ? 'list_active' : null;
return (
<Fragment key={index}>
{item.title && (
<li className={less.courseTitle}>
<div>
<p>{item.title}</p>
</div>
</li>
)}
{item.titleName && (
<li className={className} onClick={this.changeDescription.bind(this, index)}>
<div className={less.sidebar_list}>
<div style={{ display: "flex" }}>
<FontAwesomeIcon className={less.item_icon} icon={item.iconName} />
</div>
<div className={less.titleName}>
<div>
<p>{item.titleName}</p>
</div>
</div>
</div>
</li>
)}
</Fragment>
);
});
return (
<>
<div className="abc">
<div>
<Navbar color="blue" bg="tomato" centerFlexNavbarContainer="flex" LiItem="NavBarli" MainStream="MainStream"
navbarSearchPage="Search" navbarHomePage="Home" NavbarMobileIconsBlock="mobile"
centerHeadlineNavbarColumn="center" showsidebarMobile={this.showsidebarMobile} menuMobileIsOpen={this.menuMobileIsOpen} />
<div>
{
this.state.menuMobileIsOpen ? <NavbarMobile /> : null
}
</div>
</div>
<div className={less.wrapper}>
<Menu isOpen={this.state.sidebarMobile} >
<main id="page-wrap">
<div className={less.sidebar}>
<div>
<ul onClick={this.hideMenu.bind(this)}>
{listLessons}
</ul>
</div>
</div>
</main>
</Menu>
<div>
<div className={less.main_content}>
<div className={less.main_inside_content}>
<div className={less.header}>
<div className={less.header_next_page}>
<div>
<h2>{this.props.lesson[this.state.indexDescription]["heading"]}</h2>
</div>
</div>
</div>
<div className={less.info} onClick={this.HideMenuMobileIsOpen.bind(this)}>
<div className={less.description}>
{
ReactHtmlParser(this.props.lesson[this.state.indexDescription]["data"]["description"])
}
<div className={less.btn_Next_Prev_Container}>
<div>
{
this.state.indexDescription >= 2 ?
<NextPage onClick={this.prevPage.bind(this)} > <Icon.ArrowLeft className={less.arrowLeft} /> Back </NextPage>
:
null
}
</div>
<div>
<NextPage onClick={this.nextPage.bind(this)} > Next <Icon.ArrowRight className={less.arrowRight} /> </NextPage>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
}
}

hideMenu is invalid syntax. You're kind of declaring a function in the style of a class method inside of a class method, and also trying to setState inside of the method without actually calling it.
if (window.innerWidth < 900) {
hideMenu() {
this.setState({ sidebarMobile: false })
}
}
You'd need to either...
a) Forgo attempting to call a function and simply set state:
if (window.innerWidth < 900) {
this.setState({ sidebarMobile: false })
}
b) Declare your function as a class method and call it within your condition, like this:
hideMenu() {
this.setState({ sidebarMobile: false })
}
resize() {
if (window.innerWidth > 900) {
this.setState({ sidebarMobile: true })
this.setState({ menuMobileIsOpen: false })
} else {
this.setState({ sidebarMobile: false })
}
if (window.innerWidth < 900) {
this.hideMenu()
}
}
If you're trying to create hideMenu inside of your class method, you would do this:
resize() {
const hideMenu = () => this.setState({ sidebarMobile: false })
if (window.innerWidth > 900) {
this.setState({ sidebarMobile: true })
this.setState({ menuMobileIsOpen: false })
} else {
this.setState({ sidebarMobile: false })
}
if (window.innerWidth < 900) {
hideMenu()
}
}

Related

Nothing was returned from render. This usually means a return statement is missing. Error

I can't get my head around why I'm getting this error. Does anyone know what is wrong with the code? The code worked when there was only the "class image" and the error started appearing after I added back "function App()".
App.js =>
import React, {useEffect, useState} from "react";
import "./App.css";
import Navbar from './components/Navbar/Navbar'
import "bootstrap/dist/css/bootstrap.min.css";
import UploadImages from "./components/image-upload.component";
import styled from "styled-components";
function App() {
const [url, setURL] = useState("");
const Button = styled.button`
background-color: black;
color: white;
font-size: 20px;
padding: 10px 60px;
border-radius: 5px;
margin: 10px 0px;
cursor: pointer;
`;
const [urls, setURLs] = useState([]);
useEffect(() => {
const urls = [
250940,
20622,
436625,
436444,
436509,
359245,
459090,
333933,
333916,
466350,
44831,
383010,
202660,
406317,
337349,
503448,
12617,
248662,
435805,
438545
].map(
(itemId) =>
`https://collectionapi.metmuseum.org/public/collection/v1/objects/${itemId}`
);
Promise.all(
urls.map((currUrl) =>
fetch(currUrl)
.then((response) => response.json())
.then((data) => data.primaryImage)
.catch((error) => console.log("There was a problem!", error))
)
).then((fetchedUrls) => setURLs(fetchedUrls));
}, []);
class image extends React.Component {
constructor(props) {
super(props);
this.onClickNext = this.onClickNext.bind(this)
this.onClickPrevious = this.onClickPrevious.bind(this)
const img0 = 'https://images.metmuseum.org/CRDImages/gr/original/DP146615.jpg'
const img1 = 'https://images.metmuseum.org/CRDImages/ad/original/DP253076.jpg'
const img2 = 'https://images.metmuseum.org/CRDImages/ep/original/DP146499.jpg'
const img3 = 'https://images.metmuseum.org/CRDImages/ep/original/EP1455.jpg'
const img4 = 'https://images.metmuseum.org/CRDImages/ep/original/DT2580.jpg'
const img5 = 'https://images.metmuseum.org/CRDImages/dp/original/DP821059.jpg'
const img6 = 'https://images.metmuseum.org/CRDImages/rl/original/DP295708.jpg'
const img7 = 'https://images.metmuseum.org/CRDImages/dp/original/DP805154.jpg'
this.state = {
index: 0,
imgList: [img0 ,img1, img2, img3, img4, img5, img6, img7]
}
}
// imgList: [urls[1], urls[2], urls[3], urls[4], urls[5], urls[6], urls[7], urls[8], urls[9], urls[10], urls[11], urls[12], urls[13], urls[14], urls[15], urls[16], urls[17], urls[18], urls[19], urls[20]]
onClickNext() {
if (this.state.index + 1 === this.state.imgList.length) {
this.setState({
index: 0
})
} else {
this.setState({
index: this.state.index + 1
})
}
}
onClickPrevious() {
if (this.state.index - 1 === -1) {
this.setState({
index: this.state.imgList.length -1
})
} else {
this.setState({
index: this.state.index -1
})
}
}
render() {
return (
<div>
<div className="productsContainer">
<div className="images">
<div className="images__item">
<img className="photo" src={this.state.imgList[this.state.index]}/>
</div>
<div className="images__item">
<img className="photo" src={this.state.imgList[this.state.index + 1]}/>
</div>
<div className="images__item">
<img className="photo" src={this.state.imgList[this.state.index + 2]}/>
</div>
</div>
</div>
<button onClick={this.onClickPrevious}>Previous</button>
<button onClick={this.onClickNext}>Next</button>
</div>
)
}
}
}
export default App;
Full error: App(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
You are not rendering anything in your <App>. You need to return your component. I renamed it from <Image> to <ImageCarousel>.
I also cleaned-up the modular math.
const { useEffect, useState } = React;
const images = [
'https://images.metmuseum.org/CRDImages/gr/original/DP146615.jpg',
'https://images.metmuseum.org/CRDImages/ad/original/DP253076.jpg',
'https://images.metmuseum.org/CRDImages/ep/original/DP146499.jpg',
'https://images.metmuseum.org/CRDImages/ep/original/EP1455.jpg',
'https://images.metmuseum.org/CRDImages/ep/original/DT2580.jpg',
'https://images.metmuseum.org/CRDImages/dp/original/DP821059.jpg',
'https://images.metmuseum.org/CRDImages/rl/original/DP295708.jpg',
'https://images.metmuseum.org/CRDImages/dp/original/DP805154.jpg'
];
class ImageCarousel extends React.Component {
constructor(props) {
super(props);
const { images } = props;
this.onClickNext = this.onClickNext.bind(this)
this.onClickPrevious = this.onClickPrevious.bind(this)
this.state = {
index: 0,
imgList: images
}
}
onClickNext() {
this.rotateIndex(1);
}
onClickPrevious() {
this.rotateIndex(-1);
}
rotateIndex(direction) {
const { index, imgList: { length }} = this.state;
this.setState({
index: this.calculateIndexOffset(index, direction, length)
});
}
calculateIndexOffset(start, offset, size) {
return (start + size + offset) % size;
}
indexOffset(offset = 0) {
const { index, imgList: { length }} = this.state;
return this.calculateIndexOffset(index, offset, length);
}
imageOffset(offset = 0) {
return this.state.imgList[this.indexOffset(offset)];
}
render() {
return (
<div className="imageCarousel">
<div className="productsContainer">
<div className="images">
<div className="images__item">
<img className="photo" src={this.imageOffset()}/>
</div>
<div className="images__item">
<img className="photo" src={this.imageOffset(1)}/>
</div>
<div className="images__item">
<img className="photo" src={this.imageOffset(2)}/>
</div>
</div>
</div>
<div className="buttons">
<button onClick={this.onClickPrevious}>Previous</button>
<button onClick={this.onClickNext}>Next</button>
</div>
</div>
)
}
}
const App = () => {
const [url, setURL] = useState("");
const [urls, setURLs] = useState([]);
useEffect(() => {
const urls = [
250940,
20622,
436625,
436444,
436509,
359245,
459090,
333933,
333916,
466350,
44831,
383010,
202660,
406317,
337349,
503448,
12617,
248662,
435805,
438545
].map(
(itemId) =>
`https://collectionapi.metmuseum.org/public/collection/v1/objects/${itemId}`
);
Promise.all(
urls.map((currUrl) =>
fetch(currUrl)
.then((response) => response.json())
.then((data) => data.primaryImage)
.catch((error) => console.log("There was a problem!", error))
)
).then((fetchedUrls) => setURLs(fetchedUrls));
}, []);
return <ImageCarousel images={images} />
}
ReactDOM.render(<App />, document.getElementById("react"));
.imageCarousel {
display: grid;
grid-template-columns: 1fr;
grid-row-gap: 0.5em;
}
.imageCarousel .productsContainer .images {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.images__item {
display: flex;
justify-content: center;
}
.images__item .photo {
max-height: 160px;
flex: 1;
}
.imageCarousel .buttons {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-column-gap: 1em;
justify-content: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

How to reset interval and call api with interval in a function in react js

Hello I wanted to reset my set interval whenever my function is been called iam calling my interval in componentDidmount in react js and I want it to reset previous interval whenever that function is called iam also changing the value of api in that same function and now i want it to behave with the changes. The function is all three of the keyPressed Below is my code.
import React, { Component } from "react";
import { HotKeys } from "react-hotkeys";
import Axios from "axios";
class Test extends Component {
constructor(props) {
super(props);
this.state = {
seconds: 3,
color: null,
items: [],
currentItem: [],
index: 0
};
this.handleChange = this.handleChange.bind(this);
this.keyMap = {
DONT_APPLIES: ["a", "A"],
APPLIES: ["s", "S"],
STRONGLY_APPLIES: ["d", "D"]
};
this.handlers = {
DONT_APPLIES: e => {
this.keyPressed();
},
APPLIES: e => {
this.keyPressed1();
},
STRONGLY_APPLIES: e => {
this.keyPressed2();
}
};
}
keyPressed(e) {
const { index, items } = this.state;
const nextQuestion = index + 1;
this.setState({ currentItem: items[nextQuestion], index: nextQuestion });
console.log(this.state);
}
keyPressed1(e) {
const { index, items } = this.state;
const nextQuestion = index + 1;
this.setState({ currentItem: items[nextQuestion], index: nextQuestion });
console.log(this.state);
}
keyPressed2(e) {
const { index, items } = this.state;
const nextQuestion = index + 1;
this.setState({ currentItem: items[nextQuestion], index: nextQuestion });
console.log(this.state);
}
handleChangeColor = newColor => {
this.setState({
color: newColor
});
};
componentDidMount() {
this.myInterval = setInterval(() => {
const { seconds } = this.state;
if (seconds > 0) {
this.setState(({ seconds }) => ({
seconds: seconds - 1
}));
} else if (seconds == 0) {
return this.handleChangeColor("#840000");
}
}, 1000);
Axios.get("https://jsonplaceholder.typicode.com/users")
.then(response => {
console.log(response);
this.setState({
items: response.data.result.items,
currentItem: response.data.result.items[0],
index: 0
});
})
.catch(error => {
console.log(error);
});
}
componentWillUnmount() {
clearInterval(this.myInterval);
}
render() {
const { seconds } = this.state;
const timebox = {
width: "50px",
height: "20px"
};
const { currentItem } = this.state;
return (
<HotKeys keyMap={this.keyMap} handlers={this.handlers}>
<div id="wrapper" class="myleaty">
<div class="myleaty-holder">
<div class="container">
<div style={{ background: this.state.color }} class="myleaty-box">
<div style={timebox}>
<h2>{seconds}</h2>
</div>
<div class="logo">
<a href="#">
<img src="images/logo.png" alt="leaty" />
</a>
</div>
<p key={currentItem.id}>{currentItem.pqDetail}</p>
<div class="btn-row">
<button className="btn btn1">Does not Applies</button>
<button className="btn">Applies</button>
<button className="btn btn1">Strongly Applies</button>
</div>
</div>
</div>
</div>
</div>
</HotKeys>
);
}
}
export default Test;

How to change style of single component onClick in react.js

I try to build a to-do-list in react.
I have 2 components so far:
The first one handles the input:
import React from 'react';
import ListItems from './ListItems.js';
class InputComponent extends React.Component {
constructor(){
super();
this.state = {
entries: []
}
this.getText = this.getText.bind(this);
}
getText() {
if(this._inputField.value !== '') {
let newItem = {
text: this._inputField.value,
index: Date.now()
}
this.setState((prevState) => {
return {
entries: prevState.entries.concat(newItem)
}
})
this._inputField.value = '';
this._inputField.focus();
}
}
render() {
return(
<div>
<input ref={ (r) => this._inputField = r } >
</input>
<button onClick={ () => this.getText() }>Go</button>
<div>
<ListItems
entries={this.state.entries}
/>
</div>
</div>
)
}
}
export default InputComponent;
The second one is about the actual entries in the list:
import React from 'react';
class ListItems extends React.Component {
constructor() {
super();
this.lineThrough = this.lineThrough.bind(this);
this.listTasks = this.listTasks.bind(this);
}
lineThrough(item) {
console.log(item);
//item.style = {
// textDecoration: 'line-through'
//}
}
listTasks(item) {
return(
<li key = { item.index }>
<div
ref = { (r) => this._itemText = r }
style = {{
width: 50 + '%',
display: 'inline-block',
backgroundColor: 'teal',
color: 'white',
padding: 10 + 'px',
margin: 5 + 'px',
borderRadius: 5 + 'px'
}}
>
{ item.text }
</div>
<button onClick={ () => this.lineThrough(this._itemText) }>Done!</button>
<button>Dismiss!</button>
</li>
)
}
render() {
let items = this.props.entries;
let listThem = items.map( this.listTasks );
return(
<ul style = {{
listStyle: 'none'
}}>
<div>
{ listThem }
</div>
</ul>
)
}
}
export default ListItems;
As you can see, i want to have two buttons for each entry, one for the text to be line-through, and one to delete the entry.
I am currently stuck at the point where i try to address a specific entry with the "Done!" button to line-through this entry's text.
I set a ref on the div containing the text i want to style and pass that ref to the onClick event handler.
Anyways, the ref seems to be overwritten each time i post a new entry...
Now, always the last of all entries is addressed. How can i properly address each one of the entries?
What would be the best practice to solve such a problem?
you could pass an additional prop with index/key of the todo into every item of your todo list. With passing event object to your handler lineThrough() you can now get the related todo id from the attributes of your event target.
Kind regards
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
todos: []
}
this.done = this.done.bind(this);
}
done(id) {
this.state.todos[id].done();
}
render() {
return (
this.state.todos.map(t => <Todo item={t} onDone={this.done} />)
);
}
}
const Todo = ({item, onDone}) => {
return (
<div>
<h1>{item.title}</h1>
<button onClick={() => onDone(item.id)}>done</button>
</div>
)
}
You need map listItems then every list item get its own ref
import React from 'react';
import ReactDOM from 'react-dom';
class ListItems extends React.Component {
constructor() {
super();
this.lineThrough = this.lineThrough.bind(this);
}
lineThrough(item) {
item.style.textDecoration = "line-through";
}
render() {
return(
<ul style = {{
listStyle: 'none'
}}>
<div>
<li key={this.props.item.index}>
<div
ref={(r) => this._itemText = r}
style={{
width: 50 + '%',
display: 'inline-block',
backgroundColor: 'teal',
color: 'white',
padding: 10 + 'px',
margin: 5 + 'px',
borderRadius: 5 + 'px'
}}
>
{this.props.item.text}
</div>
<button onClick={() => this.lineThrough(this._itemText)}>Done!</button>
<button>Dismiss!</button>
</li>
</div>
</ul>
)
}
}
class InputComponent extends React.Component {
constructor(){
super();
this.state = {
entries: []
}
this.getText = this.getText.bind(this);
}
getText() {
if(this._inputField.value !== '') {
let newItem = {
text: this._inputField.value,
index: Date.now()
}
this.setState((prevState) => {
return {
entries: prevState.entries.concat(newItem)
}
})
this._inputField.value = '';
this._inputField.focus();
}
}
render() {
return(
<div>
<input ref={ (r) => this._inputField = r } >
</input>
<button onClick={ () => this.getText() }>Go</button>
<div>
{this.state.entries.map((item, index) => {
return <ListItems key={index} item={item} />
})}
</div>
</div>
)
}
}

Carousel with js and css in REACT

I created a carousel in html, css and js. The below are the respective codes.
HTML:
<div class="doorHardwareTile" id="dh">
<img class="mySlidesDH slide-to-right" src="images/Folder1/1.jpg?" alt="" />
<img class="mySlidesDH slide-to-right" src="images/Folder1/2.jpg?" alt="" />
<img class="mySlidesDH slide-to-right" src="images/Folder1/3.jpg?" alt="" />
<img class="mySlidesDH slide-to-right" src="images/Folder1/4.jpg?" alt="" />
<img class="mySlidesDH slide-to-right" src="images/Folder1/5.jpg?" alt="" />
<img class="mySlidesDH slide-to-right" src="images/Folder1/6.jpg?" alt="" />
<div class="overlayDH">
<img src="images/Folder1/0.png?" alt="" />
</div>
</div>
CSS:
.slide-to-right {
position: relative;
animation: animateright 0.5s;
}
#keyframes animateright {
from {
right: -300px;
opacity: 0;
}
to {
right: 0;
opacity: 1;
}
}
.doorHardwareTile {
display: flex;
overflow: hidden;
width: 560px;
height: 373px;
min-width: auto;
min-height: auto;
margin-bottom: 16px;
}
.mySlidesDH {
display: none;
}
.overlayDH {
position: absolute;
width: 560px;
height: 373px;
z-index: 800;
opacity: 0;
transition: 0.5s ease;
}
.overlayDH img {
object-fit: cover;
width: 100%;
height: 100%;
align-content: center;
}
.doorHardwareTile:hover .overlayDH {
opacity: 1;
}
JS:
$(function doorHardwareSS() {
var myIndex = 0;
carouselDH();
function carouselDH() {
var i;
var totalElements = document.getElementsByClassName("mySlidesDH");
for (i = 0; i < totalElements.length; i++) {
totalElements[i].style.display = "none";
}
myIndex++;
if (myIndex > totalElements.length) {
myIndex = 1;
}
totalElements[myIndex - 1].style.display = "block";
setTimeout(carouselDH, 5000);
}
});
This worked perfectly in the html, css and js.
However, when I tried to replicate the same in REACT. It throws error in the following line
totalElements[i].style.display = "none";
The error is "Uncaught TypeError: Cannot read property 'style' of undefined."
The images that I want in the carousel are retrieved from DB in a class based component.
I'm just a beginner in REACT. I would be thankful for any help in achiving the same result.
The below is the REACT code which is called in a class based component.
import React from "react";
const ImageSlide = props => {
if (
props.imagePath === undefined ||
props.imagePath === null ||
props.imagePath.length === 0
)
return null;
return (
<div className={props.styles}>
{props.imagePath.map(image => {
const path = props.svgsArray.find(str => str.indexOf(image.hash) > 1);
// console.log(path);
return (
<img
className="mySlidesDH slide-to-right"
key={image.id}
src={path}
alt={props.styles}
/>
);
})}
<div className={props.styles2}>
<img src={require("./images/1_Door_hardware/0.png?")} alt="" />
</div>
</div>
);
};
export default ImageSlide;
Please note that value doorHardwareTile is passed through props.styles and value overlayDH is passed through props.styles2
For React try the following package:
https://github.com/FormidableLabs/react-animations
For React Native:
https://facebook.github.io/react-native/docs/animations
Here is an example but its for react-native it might have the same idea of how you could do a simple right slide, but still you need a function to fade out or set opacity to zero of the container, once it is slide to right and have another function to set it to its original position with replacing picture inside the container.
First set position of container inside the this.state:
this.state = {
containerRightSlideAnim: new Animated.ValueXY({x: 0, y: 0})
}
And inside the constructor set position you would like for X:
this.containerRightSlide = Animated.timing(this.state.containerRightSlideAnim, {
toValue: {x: 200, y: 0},
duration: 10000,
//speed: 0.1,
easing: Easing.in(Easing.ease)
})
Make a function that triggers the right slide animation:
triggerRightSlide(){
this.containerRightSlide.start();
}
Add inside render:
render() {
const animatableRightSlideStyle = this.state.containerSlideAnim.getTranslateTransform()
return (<View>
<Animated.View style={[animatableRightSlideStyle]}></Animated.View>
</View>)
}
Here is a working prototype for Carousel with pagination in ReactJS Live Demo here
HTML
<h2>Prototype Carousel with pagination in ReactJS</h2>
<div id="app"></div>
JS React
import React from 'react'
import ReactDOM from 'react-dom'
class Pagination extends React.Component {
constructor( props ){
super( props );
}
paginationRender = ( source, activeItem, handleEvent ) => {
const items = source.map(( item, i ) => {
let itemClass = 'page-item';
if( item.id === activeItem ){
itemClass += ' active';
}
return <li key={i} className={ itemClass }>
<a className="page-link" href="#"
onClick={ e => handleEvent( e, 'clickItem', item )}>
{ i + 1 }</a>
</li>;
});
return <ul className="pagination pagination-sm justify-content-center">
<li className="page-item">
<a className="page-link" href="#"
onClick={e => handleEvent( e, 'prevItem', {}, items )}>Prev</a>
</li>
{items}
<li className="page-item">
<a className="page-link" href="#"
onClick={e => handleEvent( e, 'nextItem', {}, items )}>Next</a>
</li>
</ul>;
};
render() {
const { itemsSrc, activeItem, handleEvent } = this.props;
//console.info('MenuContent->render()', { source });
return <div>{this.paginationRender( itemsSrc, activeItem, handleEvent ) }</div>;
}
}
class Carousel extends React.Component {
constructor( props ){
super( props );
}
carouselRender = ( source, activeItem, handleEvent ) => {
//console.info('Carousel->carouselRender [0]', { source, state: this.state });
const indicators = source.map(( item, i ) => {
let itemClass = '';
if( item.id === activeItem ){
itemClass += ' active';
}
//console.info('Carousel->carouselRender [3]', { id: item.id, item, pageItemClass, activeItem: activeItem });
return <li key={i} data-target="#demo" data-slide-to="1" className={ itemClass }
onClick={ e => handleEvent( e, 'clickItem', item )}>></li>;
});
const imgs = source.map(( item, i ) => {
let itemClass = 'carousel-item';
if( item.id === activeItem ){
itemClass += ' active';
}
//console.info('Carousel->carouselRender [5]', { id: item.id, item, pageItemClass, activeItem: activeItem });
return <div key={i} className={ itemClass }>
<img src={item.src} className="img-fluid" alt="New York" />
</div>;
});
//console.info('Carousel->carouselRender [7]', { });
return <div id="demo" className="carousel slide" data-ride="carousel">
<ul className="carousel-indicators">
{ indicators }
</ul>
<div className="carousel-inner">
{ imgs }
</div>
<a className="carousel-control-prev" href="#demo" data-slide="prev">
<span className="carousel-control-prev-icon"
onClick={e => handleEvent( e, 'prevItem', {}, source )}>
</span>
</a>
<a className="carousel-control-next" href="#demo" data-slide="next">
<span className="carousel-control-next-icon"
onClick={e => handleEvent( e, 'nextItem', {}, source )}>
</span>
</a>
</div>;
};
render() {
const { itemsSrc, activeItem, handleEvent } = this.props;
//console.info('MenuContent->render()', { source });
return <div>{this.carouselRender( itemsSrc, activeItem, handleEvent ) }</div>;
}
}
const inputProps = {
itemsSrc: [
{ id: 0,
name: 'Los Angeles',
level: 'basic',
src: 'https://www.w3schools.com/bootstrap4/la.jpg'
},
{
id: 1,
name: 'Chicago',
level: 'basic',
src: 'https://www.w3schools.com/bootstrap4/chicago.jpg'
},
{
id: 2,
name: 'New York',
level: 'advanced',
src: 'https://www.w3schools.com/bootstrap4/ny.jpg'
},
],
};
class Wrapper extends React.Component {
constructor( props ){
super( props );
this.state = {
activeItem: 0,
};
}
handleEvent = ( e, actionType, item, items ) => {
e.preventDefault();
let itemsLength, activeItem;
switch( actionType ){
case 'clickItem':
//console.info('MenuContent->paginationRender', { actionType, id: item.id, item });
this.setState({ activeItem: item.id });
break;
case 'prevItem':
activeItem = this.state.activeItem;
if ( activeItem === 0 ){
break;
}
activeItem -= 1;
this.setState({ activeItem });
break;
case 'nextItem':
itemsLength = items.length;
activeItem = this.state.activeItem;
if (activeItem === itemsLength -1) {
break;
}
activeItem += 1;
this.setState({ activeItem });
break;
}
//console.info('MenuContent->handleEvent()', { actionType, item, items });
}
render(){
let props = this.props;
const { activeItem } = this.state;
props = { ...props, handleEvent: this.handleEvent, activeItem };
return <div className="App">
<div className="container-fluid">
<div className="row">
<div className="col-1">
</div>
<div className="col-10">
<Pagination { ...props }/>
<Carousel { ...props }/>
</div>
<div className="col-1">
</div>
</div>
</div>
</div>;
}
}
ReactDOM.render(<Wrapper { ...inputProps }/>, document.getElementById('app'));

ReactJS - put overflown elements into a "..." dropdown button

I have following UI element on the top of my page:
|[Static1] [Dynamic1] [Dynamic2] [Dynamic3] [Static2]|
So Static1 is some logo component that sticks to the left, Static2 is some user menu component that sticks to the right.
Now inside of it I have a collection component that displays several dynamic elements loaded from the DB.
All is good, if there are not too much of those components, but if there are more, I don't wan't any linebreaks, only some fort of "More" menu, something like:
|[Static1] [Dynamic1] [Dynamic2] [Dynamic3] [Dynamic4][...][Static2]|
and when I click the [...] button I wan't a vertical list of the dynamic components.
The list of dynamic items is stored in an ElementList component, with following code:
React.createClass({
render() {
return (
<div ref="listparent">
{ this.props.elements.map((element) => {
return <Element
ref={"element-"+element.name}
key={element.name}
})}
</div>
)
}
});
this.props.elements is a collection passed as a prop. I tried something allong those lines, but it either didn't work or worked but not on each page refresh:
export default React.createClass({
getInitialState(){
return {
visibleElements: this.props.elements,
hiddenElements: []
}
},
componentDidMount() {
this.rearrange();
},
componentDidUpdate(){
this.rearrange();
},
rearrange(){
var element = ReactDOM.findDOMNode(this.refs.listparent);
let visibleElements = [];
let hiddenElements = [];
for(var i=0; i< this.props.elements.length; i++)
{
var currentElement = this.props.elements[i];
var domElement = ReactDOM.findDOMNode(this.refs["element-"+element.name]);
if(domElement) {
if (domElement.offsetTop + domElement.offsetHeight >
element.offsetTop + element.offsetHeight ||
domElement.offsetLeft + domElement.offsetWidth >
element.offsetLeft + element.offsetWidth - 200) {
hiddenElements.push(currentElement);
}
else {
visibleElements.push(currentElement);
}
}
}
if(this.state.visibleElements.length != visibleElements.length) {
this.setState({
visibleElements: visibleElements,
hiddenElements: hiddenElements
})
}
},
render() {
return (
<div ref="listparent">
{ this.state.visibleElements.map((element) => {
return <Element
ref={"element-"+element.name}
key={element.name} />
})}
{ this.state.hiddenElements.length >0 &&
<DropdownMenu
Header="..."
>
{ this.state.hiddenElements.map((element) => {
return <Element
ref={"element-"+element.name}
key={element.name} />
})}
</DropdownMenu>
}
</div>
)
}
});
Here is a rough jsFiddle with what I want to do: https://jsfiddle.net/3uf9r8ne/
Got it working, I don't know if that's the best solution, or how robust it is, but works for me at least for now.
JsFiddle: https://jsfiddle.net/1w6m1n6h/
var Dropdown = React.createClass({
getInitialState(){
return {
isOpen: false
}
},
componentWillMount() {
document.addEventListener('click', this.handleClick, false);
},
componentWillUnmount() {
document.removeEventListener('click', this.handleClick, false);
},
handleClick: function (e) {
var component = ReactDOM.findDOMNode(this.refs.component);
if (e.target == component || $(component).has(e.target).length) {
// Inside the component
}
else{
// Outide
this.setState({ isOpen: false});
}
},
render()
{
return (
<div ref="component" className="dropdown">
<div className="dropdown-button" onClick={() => this.setState({ isOpen : !this.state.isOpen})}>{this.props.Header}</div>
{
this.state.isOpen && (
<div className="dropdown-menu" onClick={() => this.setState({ isOpen : false})}>
{React.Children.map(this.props.children, (item) => item)}
</div>
)
}
</div>
);
}
});
var Card = React.createClass({
render() {
let className = "card";
if(this.props.isHidden)
className += " is-hidden";
return (
<div className={className}>{this.props.name}</div>
)
}
});
var Cards = React.createClass({
getInitialState() {
return {
vCards: [],
hCards: [],
lastSetCards: [],
preMounted: false,
laidOut: false
};
},
rearrange() {
_.throttle(this.setState({laidOut: false, preMounted: false}), 100);
},
componentDidMount() {
window.addEventListener('resize', this.rearrange);
},
componentWillUnmount() {
window.removeEventListener('resize', this.rearrange);
},
componentDidUpdate() {
if(this.props.cards.length != this.state.lastSetCards || !this.state.preMounted) {
this.setState({
lastSetCards: this.props.cards.length,
vCards: this.props.cards,
preMounted: true,
laidOut: false
});
}
if(this.state.preMounted && !this.state.laidOut) {
var element = ReactDOM.findDOMNode(this.refs.listparent);
let visibleCards = [];
let hiddenCards = [];
for(var i=0; i< this.props.cards.length; i++)
{
var card = this.props.cards[i];
var cardElement = ReactDOM.findDOMNode(this.refs["card-"+card]);
if(cardElement) {
if (cardElement.offsetTop + cardElement.offsetHeight >
element.offsetTop + element.offsetHeight ||
cardElement.offsetLeft + cardElement.offsetWidth >
element.offsetLeft + element.offsetWidth - 160) {
hiddenCards.push(card);
}
else {
visibleCards.push(card);
}
}
}
this.setState({
vCards: visibleCards,
hCards: hiddenCards,
laidOut: true
});
}
},
render() {
return (<div className="cards-top" ref="listparent">
<div className="cards" >
{this.state.vCards.map((c)=> <Card ref={"card-"+c} key={c} name={c} />)}
</div>
<Dropdown Header="MORE">
{this.state.hCards.map((c)=> <Card isHidden={true} key={c} name={c} />)}
</Dropdown>
</div>
)
}
});
var Hello = React.createClass({
getInitialState() {
return {
cards: ["one", "two" ]
};
},
componentDidMount() {
this.setState({
cards: ["one", "two", "three", "four", "five", "six", "seven", "eight",
"nine", "ten", "eleven", "twelve", "thirteen", "fourteen"]
});
},
render: function() {
let addNew = () => {
this.state.cards.push("additional_"+this.state.cards.length);
this.setState({
cards: this.state.cards
})
};
return (
<div>
<div className="header">
<div className="logo">Logo</div>
<div className="user">User</div>
<Cards cards={this.state.cards} />
<div className="clear"></div>
</div>
<br/><br/>
<button onClick={addNew}>Add</button>
</div>);
}
});
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
.logo
{
float: left;
margin: 5px;
padding: 5px;
border: solid 1px blue;
}
.user
{
float: right;
margin: 5px;
padding: 5px;
border: solid 1px blue;
}
.header{
position: relative;
max-height: 10px;
height: 10px;
width: 100%;
}
.cards
{
position: relative;
display: inline-block;
vertical-align: top;
white-space: nowrap;
}
.clear
{
clear: both;
}
.card
{
display: inline-block;
margin: 5px;
padding: 5px;
border: solid 1px blue;
}
.cards-top
{
display: block;
white-space: nowrap;
vertical-align: top;
width: 100%;
border: green 1px solid;
}
.dropdown
{
display: inline-block;
}
.is-hidden
{
display: block;
}
.dropdown-button
{
margin: 5px;
padding: 5px;
border: solid 1px blue;
}
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>

Categories

Resources