React-slick - how to change custom arrow colour based on the page number - javascript

There are 2 custom arrows which are previous-arrow and next-arrow
There are also total 3 pages with 3 slides per page
What I want to do is whenever the page is the first page/last page, the previous arrow/next arrow will apply filter in svg, which means the previous arrow/next arrow will become black color
<img
…
filter:
"invert(3%) sepia(7%) saturate(7029%) hue-rotate(94deg) brightness(86%) contrast(93%)"
}}
/>
For example, if it’s the first page, the previous arrow will be filtered while next arrow will NOT be filtered.
Is it possible to do it?
App.js
import "./styles.css";
import React from "react";
import Slider from "react-slick";
import ArrowPrevious from "./arrow-previous.svg";
import ArrowNext from "./arrow-next.svg";
const ArrowButton = ({ imgSrc, imgAlt, onClick }) => {
return (
<button
onClick={onClick}
style={{ backgroundColor: "transparent", border: "none" }}
>
<img
src={imgSrc}
alt={imgAlt}
style={{
width: "50px",
height: "50px",
filter:
"invert(3%) sepia(7%) saturate(7029%) hue-rotate(94deg) brightness(86%) contrast(93%)"
}}
/>
</button>
);
};
export default function App() {
const settings = {
dots: true,
infinite: false,
speed: 500,
slidesToShow: 3,
slidesToScroll: 3,
prevArrow: <ArrowButton imgSrc={ArrowPrevious} imgAlt="previous-button" />,
nextArrow: <ArrowButton imgSrc={ArrowNext} imgAlt="next-button" />,
beforeChange: (current, next) => {
console.log(next);
}
};
return (
<div>
<Slider {...settings}>
<div>
<h3>1</h3>
</div>
<div>
<h3>2</h3>
</div>
<div>
<h3>3</h3>
</div>
<div>
<h3>4</h3>
</div>
<div>
<h3>5</h3>
</div>
<div>
<h3>6</h3>
</div>
<div>
<h3>7</h3>
</div>
</Slider>
</div>
);
}
Codesandbox
https://codesandbox.io/s/focused-dubinsky-9onwe?file=/src/App.js

See codesandbox
https://codesandbox.io/s/inspiring-austin-k9i86?file=/src/App.js:510-527
You just have to look for the onClick !== null
I broke your arrows into 2 separate components though i.e. ArrowButtonNext and ArrowButtonPrevious
const ArrowButtonPrevious = ({ imgSrc, imgAlt, onClick }) => {
return (
<button
onClick={onClick}
style={{ backgroundColor: "transparent", border: "none" }}
>
<img
src={imgSrc}
alt={imgAlt}
style={{
width: "50px",
height: "50px",
filter:
onClick === null
? "invert(93%) sepia(7%) saturate(7029%) hue-rotate(94deg) brightness(86%) contrast(93%)"
: "none"
}}
/>
</button>
);
};
const ArrowButtonNext = ({ imgSrc, imgAlt, onClick }) => {
return (
<button
onClick={onClick}
style={{ backgroundColor: "transparent", border: "none" }}
>
<img
src={imgSrc}
alt={imgAlt}
style={{
width: "50px",
height: "50px",
filter:
onClick === null
? "invert(93%) sepia(7%) saturate(7029%) hue-rotate(94deg) brightness(86%) contrast(93%)"
: "none"
}}
/>
</button>
);
};

I have Checked on Code sandbox and inspect the arrow ,you can change only background Color or else you need to import arrow icon from Material UI or Bootstrap

Related

Warning: React does not recognize the `PaperComponent` prop on a DOM element

I have simple modal using material ui 'Modal', i want to make it draggable, so user could move modal whereever they want simply by dragging, so i used 'Draggable' from react draggable, but i'm getting this error: Warning: React does not recognize the PaperComponent prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase papercomponent instead. If you accidentally passed it from a parent component, remove it from the DOM element.
what am i doing wrong ?
codesandbox:
https://codesandbox.io/s/draggabledialog-material-demo-forked-srw9yn?file=/demo.js
code:
import * as React from "react";
import Button from "#mui/material/Button";
import { Modal, Box } from "#material-ui/core";
import { Close } from "#material-ui/icons";
import Paper from "#mui/material/Paper";
import Draggable from "react-draggable";
export default function DraggableDialog() {
const [open, setOpen] = React.useState(false);
function PaperComponent(props) {
return (
<Draggable
handle="#draggable-dialog-title"
cancel={'[class*="MuiDialogContent-root"]'}
>
<Paper {...props} />
</Draggable>
);
}
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button variant="outlined" onClick={handleClickOpen}>
Open draggable dialog
</Button>
<Modal
open={open}
onClose={handleClose}
PaperComponent={PaperComponent}
// aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
aria-labelledby="draggable-dialog-title"
>
<div>
<form
style={{
width: "360px",
color: "white",
display: "flex",
flexDirection: "column",
backgroundColor: "#1E2328"
}}
>
<div
style={{
backgroundColor: "black",
margin: "0",
display: "flex",
alignItems: "center",
height: "56px",
width: "360px",
color: "white",
justifyContent: "space-between"
}}
m={2}
>
<Box
style={{
color: "#E9ECEC",
fontSize: "21px"
}}
>
Countries{" "}
</Box>
<button
style={{ color: "white" }}
onClick={handleClose}
aria-label="close-settings-popup"
>
<Close />
</button>
</div>
<div style={{ height: "100%" }}>
<div>
Country Name
<p>Germany</p>
<p>France</p>
</div>
</div>
</form>
</div>
</Modal>
</div>
);
}
Modal component does not recognize PaperComponent that you passing to it as prop,
if you only want modal to be draggable modify your code like so:
import * as React from "react";
import Button from "#mui/material/Button";
import { Modal, Box } from "#material-ui/core";
import { Close } from "#material-ui/icons";
import Paper from "#mui/material/Paper";
import Draggable from "react-draggable";
export default function DraggableDialog() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button variant="outlined" onClick={handleClickOpen}>
Open draggable dialog
</Button>
<Modal
open={open}
onClose={handleClose}
// aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
aria-labelledby="draggable-dialog-title"
>
<Draggable>
<div>
<form
style={{
width: "360px",
color: "white",
display: "flex",
flexDirection: "column",
backgroundColor: "#1E2328"
}}
>
<div
style={{
backgroundColor: "black",
margin: "0",
display: "flex",
alignItems: "center",
height: "56px",
width: "360px",
color: "white",
justifyContent: "space-between"
}}
m={2}
>
<Box
style={{
color: "#E9ECEC",
fontSize: "21px"
}}
>
Countries{" "}
</Box>
<button
style={{ color: "white" }}
onClick={handleClose}
aria-label="close-settings-popup"
>
<Close />
</button>
</div>
<div style={{ height: "100%" }}>
<div>
Country Name
<p>Germany</p>
<p>France</p>
</div>
</div>
</form>
</div>
</Draggable>
</Modal>
</div>
);
}
https://codesandbox.io/s/draggabledialog-material-demo-forked-sx2npc?file=/demo.js

React is only passing the last object in my array to a component

I have a react component where I map through a list of clients and display each client in a card.
return (
<div className='VolunteerClientsTab'>
{volunteerClients && volunteerClients.map((client) => (
<React.Fragment key={client.id}>
<div className='VolunteerClientsTab__card'>
<Avatar style={{ alignSelf: 'center', marginTop: '.5rem' }}>{client.first_name[0]}{client.last_name[0]}</Avatar>
<h2>{client.first_name} {client.last_name}</h2>
<h4>Details</h4>
<p><AiOutlineMail style={iconStyles} /> {client.email}</p>
<p><AiOutlinePhone style={iconStyles} /> {formatPhoneNumber(client.contact_number)}</p>
<h4 style={{ marginTop: '1rem' }}>Actions</h4>
<p onClick={handleOpenClientNeedsModal} className='hover-underline'><BiDonateHeart style={iconStyles} />View Needs</p>
<p className='hover-underline'><HiOutlineDocumentReport style={iconStyles} />Write Report</p>
<p className='hover-underline'><FiVideo style={iconStyles} />Contact Client</p>
</div>
<ClientNeeds open={openClientNeedsModal} handleClose={handleCloseClientNeedsModal} client={client} />
</React.Fragment>
))}
</div>
)
};
ClientNeeds is a component that renders an MUI modal to display additional client information. I am passing it the client object within the loop but when I open the modal only the client of the last index in the volunteerClients array was passed to all the modal components. Does anyone have any idea why this is happening?
ClientNeeds component
import React from 'react';
import Box from '#mui/material/Box';
import Modal from '#mui/material/Modal';
import PropTypes from 'prop-types';
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
const ClientNeeds = ({ open, handleClose, client }) => {
return (
<div>
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<h2>{client.email}</h2>
</Box>
</Modal>
</div>
)
};
ClientNeeds.propTypes = {
open: PropTypes.bool,
handleClose: PropTypes.func,
client: PropTypes.object
};
export default ClientNeeds;
MY SOLUTION
Passing the client onClick to an additional global state object and passing that state object to the modal,
const [selectedClient, setSelectedClient] = useState(null)
also only rendering the clientNeedsModal is there is an object in that state.
<div className='VolunteerClientsTab'>
{volunteerClients && volunteerClients.map((client) => (
<React.Fragment key={client.id}>
<div className='VolunteerClientsTab__card'>
<Avatar style={{ alignSelf: 'center', marginTop: '.5rem' }}>{client.first_name[0]}{client.last_name[0]}</Avatar>
<h2>{client.first_name} {client.last_name}</h2>
<h4>Details</h4>
<p><AiOutlineMail style={iconStyles} /> {client.email}</p>
<p><AiOutlinePhone style={iconStyles} /> {formatPhoneNumber(client.contact_number)}</p>
<h4 style={{ marginTop: '1rem' }}>Actions</h4>
<p onClick={() => handleOpenNeeds(client)} className='hover-underline'><BiDonateHeart style={iconStyles} />View Needs</p>
<p className='hover-underline'><HiOutlineDocumentReport style={iconStyles} />Write Report</p>
<p className='hover-underline'><FiVideo style={iconStyles} />Schedule Meeting</p>
</div>
{selectedClient ? (
<ClientNeeds open={openClientNeedsModal} handleClose={handleCloseClientNeedsModal} client={selectedClient} />
) : null}
</React.Fragment>
))}
</div>
const handleCloseClientNeedsModal = () => {
setSelectedClient(null)
setOpenClientNeedsModal(false);
}
const handleOpenNeeds = (client) => {
setSelectedClient(client)
handleOpenClientNeedsModal()
}
This allows me to pass any individual object within my array to the modal component as originally desired

Drag and drop images in React

I'm trying to implement drag and drop behaviour using React JS and react-dropzone library with showing thumbnails.
The code is as follows:
import React from "react";
import ReactDOM from "react-dom";
import Dropzone from "react-dropzone";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dropzone1: [],
dropzone2: []
};
}
addFilesToDropzone(files, dropzone) {
let files_with_preview = [];
files.map(file => {
file["preview"] = URL.createObjectURL(file);
files_with_preview.push(file);
});
const new_files = [...this.state[dropzone], ...files_with_preview];
this.setState({ [dropzone]: new_files });
}
render() {
return (
<div className="App">
<Dropzone
onDrop={files => {
this.addFilesToDropzone(files, "dropzone1");
}}
>
{({ getRootProps, getInputProps }) => (
<div {...getRootProps()} className="">
<input {...getInputProps()} />
<div style={{ height: 100, backgroundColor: "yellow" }}>
Drop some files here
{dropzone1.map(file => (
<img
src={file.preview}
alt={file.path}
style={{ width: 40, height: 40 }}
/>
))}
</div>
</div>
)}
</Dropzone>
<div style={{ display: "flex", flexDirection: "row", marginTop: 25 }}>
<div style={{ width: "100%" }}>
DROPZONE 2
<Dropzone
onDrop={files => {
this.addFilesToDropzone(files, "dropzone2");
}}
>
{({ getRootProps, getInputProps }) => (
<div {...getRootProps()} className="">
<input {...getInputProps()} />
<div style={{ height: 100, backgroundColor: "yellow" }}>
Drop some files here
{this.state.dropzone2.map(file => (
<img
src={file.preview}
alt="dsds"
style={{ width: 40, height: 40 }}
/>
))}
</div>
</div>
)}
</Dropzone>
</div>
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Here is the example on codesandbox.
Everything works fine when I drag files from a folder on my computer, but I want to be able to drag thumbnails generated with dropzone 1 to a dropzone 2. But that doesn't work.
Any idea how to do that?
Yes, that doesn't work because that's not what react-dropzone is designed for. Quote from the website,
Simple React hook to create a HTML5-compliant drag'n'drop zone for files.
Use react-dnd or react-beautiful-dnd instead.
You can use another package: react-file-drop

trigger on the buttons in the slider slick

I need to click on the custom arrows, what would the slider work. I know that there is a trigger in JQuery or something, but what can i do in react ?
You can see api slick-slider on this link https://react-slick.neostack.com/docs/example/custom-arrows
..................................................................................................................................................................
import React, { Component } from "react";
import Slider from "react-slick";
function SampleNextArrow(props) {
const { className, style, onClick } = props;
return (
<div
className={className}
style={{ ...style, display: "block", background: "red" }}
onClick={onClick}
/>
);
}
function SamplePrevArrow(props) {
const { className, style, onClick } = props;
return (
<div
className={className}
style={{ ...style, display: "block", background: "green" }}
onClick={onClick}
/>
);
}
export default class CustomArrows extends Component {
render() {
const settings = {
dots: true,
infinite: true,
slidesToShow: 3,
slidesToScroll: 1,
nextArrow: <SampleNextArrow />,
prevArrow: <SamplePrevArrow />
};
return (
<div>
<h2>Custom Arrows</h2>
// CLICK HERE
<div><span>arrows<span><span>arrows<span></div>
<Slider {...settings}>
<div>
<h3>1</h3>
</div>
<div>
<h3>2</h3>
</div>
<div>
<h3>3</h3>
</div>
<div>
<h3>4</h3>
</div>
<div>
<h3>5</h3>
</div>
<div>
<h3>6</h3>
</div>
</Slider>
</div>
);
}
}
I found this solution
document.getElementsByClassName('slick-next')[0].click()
but I do not know if it is good to use in react

infinite scroll not working properly in React

I am using infinite scroll plugin for react.js and for some reason it is not working the way it is supposed to work.
The problem is that all the requests are made at once when the page loads, and not like for example a request should be made for each time I scroll.
My code looks like below:
import React from 'react';
import {Route, Link} from 'react-router-dom';
import FourthView from '../fourthview/fourthview.component';
import {withRouter} from 'react-router';
import {Bootstrap, Grid, Row, Col, Button, Image, Modal, Popover} from 'react-bootstrap';
import traineeship from './company.api';
import Header from '../header/header.component';
import InfiniteScroll from 'react-infinite-scroller';
require('./company.style.scss');
class Traineeship extends React.Component {
constructor(props) {
super(props);
this.state = {
companies: [],
page: 0,
resetResult: false,
hasMore: true,
totalPages: null,
totalElements: 0,
};
}
componentDidMount() {
this.fetchCompanies(this.state.page);
}
fetchCompanies = page => {
let courseIds = '';
this.props.rootState.filterByCourseIds.map(function (course) {
courseIds = courseIds + '' + course.id + ',';
});
traineeship.getAll(page, this.props.rootState.selectedJob, courseIds.substring(0, courseIds.length - 1), this.props.rootState.selectedCity).then(response => {
if (response.data) {
const companies = Array.from(this.state.companies);
if(response.data._embedded !== undefined){
this.setState({
companies: companies.concat(response.data._embedded.companies),
totalPages: response.data.page.totalPages,
totalElements: response.data.page.totalElements,
});
}
if (page >= this.state.totalPages) {
this.setState({hasMore: false});
}
} else {
console.log(response);
}
});
};
render() {
return (
<div className={"wrapperDiv"}>
{/*{JSON.stringify(this.props.rootState)}*/}
<div className={"flexDivCol"}>
<div id="header2">
<div style={{flex: .05}}>
<img src="assets/img/icArrowBack.png" onClick={() => this.props.history.go(-1)}/>
</div>
<div style={{flex: 3}}>
<Header size="small"/>
</div>
</div>
<div id="result">
<div className={"search"}>
<h2 style={{fontSize: 22}}>Harjoittelupaikkoja</h2>
<p className={"secondaryColor LatoBold"} style={{fontSize: 13}}>{this.state.totalElements} paikkaa löydetty</p>
</div>
<div className={"filters"}>
<h5 style={{marginTop: '30px', marginBottom: '10px'}} className={"primaryColor"}>
<strong>Hakukriteerit</strong></h5>
{
this.props.rootState.filters.map((filter, key) => (
<div key={key} className={"filter"}>{filter.title}</div>
))
}
</div>
<div className={"searchResults"}>
<h5 style={{marginTop: '30px', marginBottom: '10px'}} className={"primaryColor"}>
<strong>Hakutulokset</strong></h5>
<InfiniteScroll
pageStart={0}
loadMore={this.fetchCompanies}
hasMore={this.state.hasMore}
loader={<div className="loader" key={0}>Loading ...</div>}
useWindow={false}
>
{
this.state.companies.map((traineeship, key) => (
<div id={"item"} key={key}>
<div className={"companyInfo"}>
<div className={"heading"}>
<div id={"companyDiv"}>
<p className={"LatoBlack"} style={{
fontSize: '18px',
lineHeight: '23px'
}}>{traineeship.name}</p>
</div>
{
traineeship.mediaUrl == null
? ''
:
<div id={"videoDiv"}>
<div className={"youtubeBox center"}>
<div id={"youtubeIcon"}>
<a className={"primaryColor"}
href={traineeship.mediaUrl}>
<span style={{marginRight: '3px'}}><Image
src="http://www.stickpng.com/assets/images/580b57fcd9996e24bc43c545.png"
style={{
width: '24px',
height: '17px'
}}/></span>
<span> <p style={{
fontSize: '13px',
lineHeight: '24px',
margin: 0,
display: 'inline-block'
}}>Esittely</p></span>
</a>
</div>
<div id={"txtVideo"}>
</div>
</div>
</div>
}
</div>
<div className={"location"}>
<div id={"locationIcon"}>
<Image src="assets/img/icLocation.png"
style={{marginTop: '-7px'}}/>
</div>
<div id={"address"}>
{
traineeship.addresses.map((address, key) => {
return (
<a href={"https://www.google.com/maps/search/?api=1&query=" + encodeURI("Fredrikinkatu 4, Helsinki")}>
<p key={key} className={"primaryColor"} style={{fontSize: '13px'}}>{address.street}, {address.city}</p>
</a>
)
})
}
</div>
</div>
<div className={"companyDescription"}>
<p className={"secondaryColor"} style={{
fontSize: '14px',
lineHeight: '20px'
}}>{traineeship.description}</p>
</div>
<div>
{
traineeship.images.map((image, key) => {
return (
<img id={"thumbnail"} width={"100%"}
src={image.url}
style={{
width: '80px',
height: '80px',
marginRight: '10px',
marginBottom: '10px'
}}
alt=""
key={key}
/>
)
})
}
</div>
<div className={"companyContacts"} style={{marginTop: '20px'}}>
<p className={"contactInfo"}>URL: {traineeship.website}</p>
<p className={"contactInfo"}>Email: {traineeship.email}</p>
<p className={"contactInfo"}>Puh: {traineeship.phonenumber}</p>
<p className={"contactInfo"}>Contact: {traineeship.contact}</p>
</div>
</div>
</div>
))
}
</InfiniteScroll>
</div>
</div>
</div>
</div>
);
}
}
export default withRouter(Traineeship);
What can I do so I can eliminate all the request are made when the page is load, I mean this is even worse sending let say 20 request one after another within a second or so.
Any suggestion what is wrong with my code?
by removing useWindow={false} it is working now!
Update: Haven't seen that you are using react-infinite-scroller. If you want to build the loader yourself, see my previous answer. With the plugin you can set a threshold.
The answer lies in here: Question: Infinite Scrolling
What you basically need to do is to set a variable in state, isLoading: false, and change it when data comes in via fetch, when data loading done set it back to false. In your infinite scroll function check (this.state.isLoading).

Categories