ReactJS, Swiper slider with axios - javascript

I have a Swiper slider on a react website, when I take the data from a local json file everything works fine. I had to take the data from public foler so I used axios but I can't scroll anymore in the slider. I think it's a conflict between the Axios and the Swiper plugin but I have no idea how to solve it.
Thanks! :)
Here is the code from the page:
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import Loader from "../container/Loader";
import { Helmet } from "react-helmet";
import { Col } from "react-bootstrap";
import Cookies from "../components/cookies";
import LayoutDefault from "../container/LayoutDefault";
import HeaderProject from "../components/header/HeaderProject";
import ImageSlider from "../container/ImageSlider";
const ProjectPage = ({ match }) => {
const { params: { projectId } } = match;
const [projects, setProjects] = useState(null)
useEffect(() => {
var isCancelled = false;
axios.get("./projects.json").then(
(response) => !isCancelled ? setProjects(response.data) : console.log("is canceled")
).catch(
(err) => console.log(err)
)
}, [])
const goToPreviousPage = () => {
if (window.history.length === 1) {
window.location = "/"
} else {
window.history.back();
}
}
return (
<Loader>
<Helmet>
<title>TheBrandBar | {projects ? projects[projectId - 1].title : ""}</title>
</Helmet>
<Cookies />
<LayoutDefault className="template-color-2 bg_color--4 project-page">
<button onClick={goToPreviousPage} className="page-close" />
<Col>
<HeaderProject
title={projects ? projects[projectId - 1].title : ""}
description={projects ? projects[projectId - 1].description : ""}
/>
</Col>
<ImageSlider
index={projectId}
projects = {projects}
/>
</LayoutDefault>
</Loader>
);
};
export default ProjectPage;
and imageSlider component
import React, { useState } from 'react';
import { Col } from "react-bootstrap";
import SliderSwiper from "../components/swiper";
const ImageSlider = ({ index, projects }) => {
const [swiper, updateSwiper] = useState(null);
const settings = {
slidesPerView: "auto",
spaceBetween: 0,
autoplay: false,
mousewheel: true,
loop: false,
freeMode: true,
};
const goNext = () => {
if (swiper !== null) {
swiper.slideNext();
}
};
// const goPrev = () => {
// if (swiper !== null) {
// swiper.slidePrev();
// }
// };
return (
<div className="pt--10 pb-10">
<SliderSwiper
reference={updateSwiper}
settings={settings}
>
{
projects ? projects[index - 1].images.map((image) => (
<div key={image} className="image-slide mt--15">
<img src={`${process.env.PUBLIC_URL}/projects/${index}/${image}`} alt="" />
</div>
)) : ""
}
</SliderSwiper>
{/* <button onClick={goPrev} className="swipper-btn swiper-btn-prev">
<i className="fa fa-angle-left" />
</button> */}
<Col>
<div onClick={goNext} className="scroll-btn mt--25">
<span>SCROLL TO SEE MORE</span>
<span className="btn-arrow" />
</div>
</Col>
</div>
);
};
export default ImageSlider;

Related

React js: Stepwise Progress Bar rerendering an element

I am creating a progress bar using the package - react-step-progress-bar
My progress bar code is as below (This is just the standard code of the package)
For simplicity, i am just creating two steps
import React, { useEffect } from "react";
import "react-step-progress-bar/styles.css";
import { ProgressBar, Step } from "react-step-progress-bar";
const LoadingBar = (props) => {
console.log('Logging inside loading bar',props.progressBar)
return (
<div className="w-[50%] z-50">
<ProgressBar
percent={props.progressBar}
fillBackground="linear-gradient(to right, #fefb72, #f0bb31)"
>
<Step transition="scale">
{({ accomplished }) => (
<img
style={{ filter: `grayscale(${accomplished ? 0 : 80}%)`, transform: "" }}
width="60"
src="/loadingBar/verifiedHashFiles.png"
alt=""
/>
)}
</Step>
<Step transition="scale">
{({ accomplished }) => (
<img
style={{ filter: `grayscale(${accomplished ? 0 : 80}%)`, transform: "" }}
width="60"
src="/loadingBar/verifiedTransaction.png"
alt=""
/>
)}
</Step>
</ProgressBar>
</div>
)
}
export default LoadingBar
I am using this to create a progressive bar in the way below in my home page
import axios from 'axios';
import React, { useContext, useEffect, useState, useCallback } from 'react'
import cuid from "cuid";
import { DataContext } from '../Context/DataContext';
import { Dropzone, FileVerificationFailed, FileVerificationSuccessful } from '../Components'
import "react-step-progress-bar/styles.css";
import LoadingBar from './LoadingBar';
export function Home() {
const [progressBar, setprogressBar] = useState(0);
const sendFileToIPFS = async (e) => {
e.preventDefault();
if (fileImg) {
try {
const formData = new FormData();
formData.append("file", fileImg);
const resFile = await axios({
method: "post",
url: "https://api.pinata.cloud/pinning/pinFileToIPFS",
data: formData,
headers: {
'pinata_api_key': `${process.env.REACT_APP_PINATA_API_KEY}`,
'pinata_secret_api_key': `${process.env.REACT_APP_PINATA_API_SECRET}`,
"Content-Type": "multipart/form-data"
},
});
setprogressBar(50)
if (certificateData.find(uploadedFile => uploadedFile.CID === resFile.data.IpfsHash)) {
setQRurl(certificateData.find(uploadedFile => uploadedFile.CID === resFile.data.IpfsHash).QRurl)
console.log('Verified')
setVerified(true)
}
else {
console.log('Failed')
setVerificationFailed(true)
unpin(resFile.data.IpfsHash)
}
setprogressBar(100)
} catch (error) {
console.log("File to IPFS: ")
console.log(error)
}
}
}
return (
....
{progressBar!=0 && (<div className='absolute ml-[5%] mt-[5%] h-[60%] w-[60%] z-50'>
<div className='flex justify-center'>
<LoadingBar progressBar={progressBar} />
</div>
</div>)}
....
50% never gets set or logged but the bar gets to 100% directly and logs it
How do i execute this?
Please help

Need help for React code fetch request delete operation

I am able to post and get data but unable to delete must be a problem with an id that I am passing to the delete note function.
these are my files:
Note.js
import React, {useState} from 'react';
import DeleteIcon from '#material-ui/icons/Delete';
import EditIcon from '#material-ui/icons/Edit';
import SaveIcon from '#material-ui/icons/Save';
function Note(props) {
function handleClick() {
props.onDelete(props.id);
}
const[edit, setEdit]=useState(false);
function editTrue() {
setEdit(!edit);
}
return(
<div className={!edit ? "note" : "note1"}>
<h1 contentEditable={edit && "true"} spellCheck="true">{props.title}</h1>
<hr/>
<p />
<p contentEditable={edit && "true"} spellCheck="true">{props.content}</p>
{!edit && <button onClick={handleClick}><DeleteIcon /></button>}
{edit ? <button onClick={editTrue}> <SaveIcon /> </button> : <button onClick={editTrue}><EditIcon /></button>}
</div>
);
}
export default Note;
App.js
import React, { useState, useEffect } from 'react';
//import { DragDropContext } from 'react-beautiful-dnd';
import Header from './Header';
import Footer from './Footer';
import Note from './Note';
import CreateArea from './CreateArea'
function App() {
const [notes, setNotes] = useState([]);
useEffect(() => {
fetch('https://react-hooks-update-ec587-default-rtdb.firebaseio.com/notes.json')
.then(response => response.json())
.then(responseData => {
const loadedNotes = [];
for( const key in responseData ) {
loadedNotes.push({
id: key,
title: responseData[key].title,
content: responseData[key].content
});
}
setNotes(loadedNotes);
});
}, []);
function addNote(newNote) {
fetch('https://react-hooks-update-ec587-default-rtdb.firebaseio.com/notes.json', {
method: 'POST',
body: JSON.stringify(newNote),
headers: { 'content-Type': 'application/json' }
}).then(response => {
return response.json();
}).then(responseData => {
setNotes(prevNotes => [
...prevNotes,
{ id: responseData.name, ...newNote }
]);
});
}
function deleteNote(noteId) {
fetch(`https://react-hooks-update-ec587-default-rtdb.firebaseio.com/notes/${noteId}.json`,
{
method: 'DELETE'
}
).then(response => {
setNotes(prevNotes => {
return prevNotes.filter((noteItem, index) => {
return index !== noteId;
});
});
});
}
return(
<div>
<Header />
<CreateArea
onAdd={addNote}
/>
{notes.map((noteItem, index) => {
return (
<Note
key={index}
id={index}
title={noteItem.title}
content={noteItem.content}
onDelete={deleteNote}
/>
);
})}
<Footer />
</div>
);
}
export default App;
what changes I can do?
when I run my file delete operation is working locally but it does not delete the note from the database
I am able to post and get data but unable to delete must be a problem with an id that I am passing to the delete note function.
May be in deleteNote in fetch url remove .json:
fetch(`https://react-hooks-update-ec587-default-rtdb.firebaseio.com/notes/${noteId}`)

How to make React App to filter only one item

Following a course by Andrei Neagoie on Udemy, I'm making this robots app that displays and filters data gotten from an API. I've customized it a little bit and added a carousel feature, but now, when I hit the searchbox and try to filter it displays more than one item. I want it displaying only one item, how can I do this?
This is the problem I'm having: https://imgur.com/fsgesBs
App.js
import React, { Component } from 'react'
//import CardList from './components/CardList';
import SearchBox from './components/SearchBox';
import Splider from './components/Splider';
class App extends Component {
constructor(){
super()
this.state = {
robots: [],
searchField: ''
}
}
componentDidMount(){
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => {
return res.json();
})
.then(users => {
this.setState({
robots: users
});
});
}
onSearchChange = (e) => {
this.setState({
searchField: e.target.value
});
}
render() {
const filtered = this.state.robots.filter(robot => {
return robot.name.toLowerCase().includes(this.state.searchField.toLowerCase());
});
// Main Render
return (
<div className="App tc">
<h1>RoboBros!</h1>
<SearchBox searchChange={this.onSearchChange}/>
<Splider robots={filtered}/>
{/* <CardList robots={filtered}/> */}
</div>
)
}
}
export default App
SearchBox.js
import React from 'react'
import '../index.css'
const SearchBox = ({ searchChange, searchField }) => {
return (
<div className="search-div">
<input className="search-box center" type="search" placeholder="Search Robots" onChange={searchChange}/>
<button className="search-btn">Search</button>
</div>
)
}
export default SearchBox;
Cards.js(Individual card items)
import React from 'react'
import '../styles/Cards.css';
const Cards = ({ name, id, email }) => {
return (
<div className="cards-wrapper dib br3 pa3 ma2 grow pointer">
<img className="cent" src={`https://robohash.org/${id}?set=set3`} alt="robots"/>
<div className="text">
<h3>{name}</h3>
<h4>{email}</h4>
</div>
</div>
)
}
export default Cards;
CardList.js
import React from 'react';
import Cards from './Cards';
const CardList = ({robots}) => {
const cardComponent = robots.map((robot, i) => {
return <Cards key={i} id={robots[i].id} name={robots[i].name} email={robots[i].email}/>;
})
return(
<div>
{cardComponent}
</div>
);
}
export default CardList;
Splider.js(Component that holds the Carousel/Slider library)
import React from 'react';
import { Splide, SplideSlide } from '#splidejs/react-splide';
import '#splidejs/splide/dist/css/themes/splide-sea-green.min.css';
import '../styles/Cards.css';
const Splider = ({robots}) => {
const cardSplide = robots.map((robot, i) => {
return (
<SplideSlide key={i} className="cards-wrapper dib br3 pa3 ma2">
<img src={`https://robohash.org/${robots[i].id}?set=set3`} alt="robots"/>
<h3>{robot.name}</h3>
<h4>{robot.email}</h4>
</SplideSlide>
);
});
return(
<Splide options={{
rewind: true,
width: '100%',
gap: '1rem',
perPage: 3,
perMove: 1,
focus: 'center',
type: 'loop',
easing: 'ease',
}}>
{cardSplide}
</Splide>
);
}
export default Splider;
The issue is with type: loop option:
import React from "react";
import { Splide, SplideSlide } from "#splidejs/react-splide";
import "#splidejs/splide/dist/css/themes/splide-sea-green.min.css";
import "../styles/Cards.css";
const Splider = ({ robots }) => {
return (
<Splide
options={{
rewind: true,
width: "100%",
gap: "1rem",
perPage: 3,
perMove: 1,
focus: "center",
//type: "loop",
easing: "ease"
}}
>
{robots.map((robot, i) => {
return (
<SplideSlide key={robot.id} className="cards-wrapper dib br3 pa3 ma2">
<img
src={`https://robohash.org/${robot.id}?set=set3`}
alt="robots"
/>
<h3>{robot.name}</h3>
<h4>{robot.email}</h4>
</SplideSlide>
);
})}
</Splide>
);
};
export default Splider;
This is the issue in splidejs project: https://github.com/Splidejs/splide/issues/145
It shows as fixed, so probably you need to wait for react-splide to include the fix as well in it's latest version.

How to pass my onSucceeded() function to the parent component?

I have 2 components OptinPage (parent) and TermsOfServices (child). Optin Page is only used for rendering the TermsOfServices component, which can be reused elsewhere in the application. I want to use my onSucceeded () function from my child component to my parent component. I don't see how to do it at all. Currently the result is such that when I click on the button that validates the TermsOfServices it seems to be an infinite loop, it goes on and on without closing my popup. Before I split my TermsOfServices component into a reusable component it worked fine. Before, all content was gathered in OptinPage. Any ideas? Thanks in advance
my TermsOfServices component:
import API from 'api';
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import {
Block,
BlockTitle,
Col,
Fab,
Icon,
Preloader,
} from 'framework7-react';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-refetch';
import ReactHtmlParser from 'react-html-parser';
class TermsOfServices extends PureComponent {
static propTypes = {
agreeTosFunc: PropTypes.func.isRequired,
agreeTos: PropTypes.object,
onSucceeded: PropTypes.func,
tos: PropTypes.object.isRequired,
};
static contextTypes = {
apiURL: PropTypes.string,
loginToken: PropTypes.string,
userId: PropTypes.string,
};
static defaultProps = {
agreeTos: {},
onSucceeded: () => {},
};
state = {
currentTos: -1,
};
componentDidUpdate(prevProps) {
const {
agreeTos,
onSucceeded,
tos,
} = this.props;
const { currentTos } = this.state;
/* Prepare for first tos after receiving all of them */
if (
prevProps.tos.pending &&
tos.fulfilled &&
tos.value.length &&
currentTos < 0
) {
this.setState({ currentTos: 0 });
}
/* When sending ToS agreement is done */
if (
prevProps.agreeTos.pending &&
agreeTos.fulfilled
) {
onSucceeded();
}
}
handleNext = () => {
const { agreeTosFunc, tos } = this.props;
const { currentTos: currentTosId } = this.state;
const termsOfServices = tos.value;
const done = currentTosId + 1 === termsOfServices.length;
this.setState({ currentTos: currentTosId + 1 });
if (done) {
agreeTosFunc(termsOfServices.map((v) => v._id));
}
};
render() {
const { tos } = this.props;
const { currentTos: currentTosId } = this.state;
const termsOfServices = tos.value;
const currentTermsOfServices = termsOfServices && termsOfServices[currentTosId];
const loaded = termsOfServices && !tos.pending && tos.fulfilled;
const htmlTransformCallback = (node) => {
if (node.type === 'tag' && node.name === 'a') {
// eslint-disable-next-line no-param-reassign
node.attribs.class = 'external';
}
return undefined;
};
return (
<div>
{ (!loaded || !currentTermsOfServices) && (
<div id="
optin_page_content" className="text-align-center">
<Block className="row align-items-stretch text-align-center">
<Col><Preloader size={50} /></Col>
</Block>
</div>
)}
{ loaded && currentTermsOfServices && (
<div id="optin_page_content" className="text-align-center">
<h1>
<FormattedMessage id="press_yui_tos_subtitle" values={{ from: currentTosId + 1, to: termsOfServices.length }} />
</h1>
<BlockTitle>
{ReactHtmlParser(
currentTermsOfServices.title,
{ transform: htmlTransformCallback },
)}
</BlockTitle>
<Block strong inset>
<div className="tos_content">
{ReactHtmlParser(
currentTermsOfServices.html,
{ transform: htmlTransformCallback },
)}
</div>
</Block>
<Fab position="right-bottom" slot="fixed" color="pink" onClick={() => this.handleNext()}>
{currentTosId + 1 === termsOfServices.length &&
<Icon ios="f7:check" aurora="f7:check" md="material:check" />}
{currentTosId !== termsOfServices.length &&
<Icon ios="f7:chevron_right" aurora="f7:chevron_right" md="material:chevron_right" />}
</Fab>
{currentTosId > 0 && (
<Fab position="left-bottom" slot="fixed" color="pink" onClick={() => this.setState({ currentTos: currentTosId - 1 })}>
<Icon ios="f7:chevron_left" aurora="f7:chevron_left" md="material:chevron_left" />
</Fab>
)}
</div>
)}
</div>
);
}
}
export default connect.defaults(new API())((props, context) => {
const { apiURL, userId } = context;
return {
tos: {
url: new URL(`${apiURL}/tos?outdated=false&required=true`),
},
agreeTosFunc: (tos) => ({
agreeTos: {
body: JSON.stringify({ optIn: tos }),
context,
force: true,
method: 'PUT',
url: new URL(`${apiURL}/users/${userId}/optin`),
},
}),
};
})(TermsOfServices);
My OptIn Page :
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import {
Link,
NavRight,
Navbar,
Page,
Popup,
} from 'framework7-react';
import { FormattedMessage, intlShape } from 'react-intl';
import './OptInPage.scss';
import TermsOfServices from '../components/TermsOfServices';
class OptinPage extends PureComponent {
static propTypes = {
logout: PropTypes.func.isRequired,
opened: PropTypes.bool.isRequired,
};
static contextTypes = {
intl: intlShape,
logout: PropTypes.func,
};
render() {
const { opened, logout } = this.props;
const { intl } = this.context;
const { formatMessage } = intl;
return (
<Popup opened={opened} className="demo-popup-swipe" tabletFullscreen>
<Page id="optin_page">
<Navbar title={formatMessage({ id: 'press_yui_tos_title' })}>
<NavRight>
<Link onClick={() => logout()}>
<FormattedMessage id="press_yui_comments_popup_edit_close" />
</Link>
</NavRight>
</Navbar>
</Page>
<TermsOfServices onSucceeded={this.onSuceeded} />
</Popup>
);
}
}
export default OptinPage;
Just add the data you want the parent to be supplied with in the child component (when it is hit) and then handle the data passed to the parent in the function that you pass in onSuccess.
This will roughly look like this:
const {useState, useEffect} = React;
function App(){
return <Child onSuccess={(data)=>{console.log(data)}}/>;
}
function Child({onSuccess}){
return <div>
<button
onClick={()=>onSuccess("this is the data from the child component")}>
Click to pass data to parent
</button>
</div>;
}
ReactDOM.render(<App/>,document.getElementById('app'));
#element {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id='app'></div>
<div id="element">
<div>node 1</div>
<div>node 2</div>
</div>
to access to parent method or attribute you should use super,
for call to the parent constructor
super([arguments]);
for call parent method
super.parentMethod(arguments);
I recommend create a method on child class and then call the parent method, not directly
for more information take a look on this
https://www.w3schools.com/jsref/jsref_class_super.asp

reactjs trying to work with a carousel by getting data from json

I'm trying to get specific url from my json file, based on url request and put it in my carousel's <p> tag as background.
For example, if user ask for htt....url/Item1 it will display only the slides from his part of json
So far i have:
public.js
import React, { Component } from 'react'
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom'
import Carousel from './carousel'
import Buttons from './buttons'
import Data from './data';
// Main App
class App extends React.Component {
render() {
return <br />
{
Data.map((item, index) => {
return (
<div id={item.index} style={{height: '100%'}}>
<Carousel loop auto widgets={[Buttons]} className="custom-class">
{ item.slides.map((c, i) =>
<p style={{backgroundImage:`url(${c.url})`,height: '100%'}}> {c.campanie}</p> )
}
</Carousel>
</div>
)})
}
}}
export default App;
and my Data.js
const Data = [
{
"id":0,
"sala":"Item1",
"slides":[ {
"url":"https://picsum.photos/id/1024/1920/1280",
"campanie":"carduri"
},
{
"url":"https://picsum.photos/id/1022/6000/3376",
"campanie":"happy-hour"
}]
},
{
"id":1,
"sala":"Item2",
"slides":[
{
"url":"https://picsum.photos/id/1022/6000/3376",
"campanie":"happy-hour"
}
]
}
];
export default Data;
See the below snippet, you can try like this
you can type as /url/Item1 , it will load only the specific images.
App.js
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route } from "react-router-dom";
import "./styles.css";
const Data = [
{
id: 0,
sala: "Item1",
slides: [
{
url: "https://picsum.photos/id/1024/1920/1280",
campanie: "carduri"
},
{
url: "https://picsum.photos/id/1022/6000/3376",
campanie: "happy-hour"
}
]
},
{
id: 1,
sala: "Item2",
slides: [
{
url: "https://picsum.photos/id/1022/6000/3376",
campanie: "happy-hour"
}
]
}
];
const Carousel = props => {
const { id } = props.match.params;
const [slides, setSlides] = useState([]);
useEffect(() => {
const filterSlides = Data.find(d => d.sala === id).slides;
setSlides(filterSlides);
}, [id]);
return (
<>
{slides.length &&
slides.map((c, i) => (
<p
key={i}
style={{ backgroundImage: `url(${c.url})`, height: "400px" }}
>
{" "}
{c.campanie}
</p>
))}
</>
);
};
class App extends React.Component {
render() {
return (
<>
<BrowserRouter>
<Route path="/url/:id" component={Carousel} />
</BrowserRouter>
</>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
working codesandbox
I have edited the code, I am trying to pass all values of the c.url into an array, which I will pass it into component.
const Content = props => {
const { id } = props.match.params;
const [sliduri, setSlides] = useState([]);
useEffect(() => {
const filterSlides = Data.find(d => d.sala === id).sliduri;
setSlides(filterSlides);
}, [id]);
let slidesArr = [];
const slidesJsx = sliduri.forEach((c, i) => {
slidesArr.concat(c.url);
});
const slides = slidesArr.concat(slidesJsx);
console.log(slides);
return (
<>
<Slideshow slides={slides} />
</>
);
};
export default Content;
so the slides var should be an array, but it's not appending values into array

Categories